c - 以下对象存储在内存中的什么位置?
问题描述
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define TEXT "Good luck on this test"
int main () {
char* cPtr = (char*)malloc(sizeof(TEXT));
strncpy(cPtr,TEXT,sizeof(TEXT));
printf("%s\n",cPtr);
free(cPtr);
return(EXIT_SUCCESS);
}
- 变量的内存
cPtr
? - 地址指向哪个
cPtr
? - 的代码
malloc()
? malloc()
调用以移动运行该程序的进程的brk 指针的代码?
我想这是:
- 堆
- 堆
- 数据段
- 共享库内存
这是对的吗?
解决方案
这实际上是一个领先的问题,因为它假定一切都将在内存中。
局部变量以及没有名称的临时值,仅在必要时才放入堆栈。可能有必要这样做的原因有很多,例如:
- 编译器是愚蠢的或通过在可能的最低优化级别进行编译而变得愚蠢。
- 目标机器的架构很奇怪,没有(或很少)寄存器(很少见)。
- 有太多的局部变量和临时值同时存在,无法将它们全部放入程序中的寄存器中,因此其中一些会“溢出”。溢出并不是一个变量的属性,而是一个特定的生命范围。因此,在某种意义上,一个变量可以四处移动(如果它有多个关联的生存范围并且它们的分配方式不同),甚至可以同时位于多个位置(取决于您如何计算临时副本,或者在涉及循环展开时明确)。
- 获取和使用局部变量的地址的方式使得编译器无法证明该变量不需要在内存中(可能会导致生存范围拆分,因此该变量实际上只是暂时在内存中)。
很可能以上都不适用(最后一项肯定不适用,地址没有被占用)所以我们应该期望cPtr
在寄存器中度过它的整个生命周期。
在面向 x64的clang上对其进行测试,我们可能会得到如下代码:
main: # @main
push rbx
mov edi, 23
call malloc
mov rbx, rax
; at this point, rbx roughly corresponds to cPtr
; it's also still in rax but rax is overwritten by the next operation
movabs rax, 32777976875610985 ; btw this weird number is a piece of string
mov qword ptr [rbx + 15], rax
movups xmm0, xmmword ptr [rip + .L.str]
movups xmmword ptr [rbx], xmm0
; rbx (cPtr) is copied to rdi in order to give it to puts as argument
mov rdi, rbx
call puts
mov rdi, rbx
call free
xor eax, eax
pop rbx
ret
.L.str:
.asciz "Good luck on this test"
以 MIPS 或 ARM 或 PowerPC 为目标,例如 GCC 显示出类似的模式,即cPtr
不在堆栈上而是在一个寄存器中(或多个寄存器,取决于您的计数方式),当然代码看起来非常不同。
上面代码的一个有趣细节是,虽然整个字符串确实出现在数据段(rodata)中,但它的一部分也作为 . 的直接操作数出现在代码段中movabs
。
推荐阅读
- ruby-on-rails - 模型对 Algolia 的更改未显示在 PRODUCTION 的 rails 控制台中
- firebase - 如何用颤振改变状态并保持当前状态?
- eclipse - 关于 Poky 中 tcf-agent_git.bb 中的错误 URI
- android - 在 Android 设备上使用 Angular Ionic 加速计事件频率在前 5 分钟减慢
- sql - SQLite 为表中的每个类别或查询中的查询创建一个表
- kotlin - Espresso:每次测试开始前我如何杀死应用程序
- android - 使用 Firebase 存储和 Firebase Firestore 创建离线第一个应用程序的最佳方法是什么?#AskFirebase
- jsf - 单击 h:commandButton 后如何显示 ap:graphicImage
- python - 使用 python 从 SSH 服务器上传文件(PyAutoIt 的替代品)
- javascript - TypeError:无法读取未定义的属性“位置”&& 无法读取未定义的属性“位置”