在一个简单的C程序中,如果I malloc
指向一个变量或数组的点,这部分内存在内存映射中分配到哪里?我对计算机编程很陌生,所以我不确定不同的变量在内存中的存储方式是如何不同的。
另外,全局变量(例如int x = 5
)在内存中存储到哪里?
最后,有没有关于C语言如何与底层硬件交互的资料?我在网上找到的都是和C语法有关的,但是我太笨了,看不懂编译器的书。
如果不清楚,请告诉我。
考虑这个例子:
int global_x = 5;
int global_y;
int main()
{
int local_a;
char* buf = malloc(100);
}
虽然以下描述并不总是如此(特别是在微小的嵌入式实现中),但现代平台上的典型程序将按照以下方式布局:
global_x
是一个初始化的全局变量。它通常存储在可执行文件的.data
部分中,当程序加载时,它与程序文本一起存在于内存的读写不可执行部分。global_y
是一个未初始化的全局变量。在程序的.bss
部分保留空间,并且在可执行文件中不占用空间。local_a
是一个本地(或"自动")变量,它存在于main的调用堆栈中。它的生命周期受限于该函数的执行时间。(即,一旦函数返回,变量就不再存在,并被丢弃。)buf
指向从堆中提取的100字节的动态分配缓冲区。堆是一个内存区域,通常会根据需要扩展以适应应用程序的内存需求。当堆空间耗尽时(由malloc
和支持的库函数决定),将从操作系统(例如Linux上的brk
或mmap
)请求额外的内存。
在Linux上,您可以查看/prod/[pid]/maps
以查看进程[pid]
的内存映射。例如:
$ cat /proc/30009/maps
00400000-0040c000 r-xp 00000000 fd:01 268784 /usr/bin/cat
0060b000-0060c000 r--p 0000b000 fd:01 268784 /usr/bin/cat
0060c000-0060d000 rw-p 0000c000 fd:01 268784 /usr/bin/cat
01a7a000-01a9b000 rw-p 00000000 00:00 0 [heap]
365ec00000-365ec20000 r-xp 00000000 fd:01 263066 /usr/lib64/ld-2.18.so
365ee1f000-365ee20000 r--p 0001f000 fd:01 263066 /usr/lib64/ld-2.18.so
365ee20000-365ee21000 rw-p 00020000 fd:01 263066 /usr/lib64/ld-2.18.so
365ee21000-365ee22000 rw-p 00000000 00:00 0
365f000000-365f1b4000 r-xp 00000000 fd:01 263128 /usr/lib64/libc-2.18.so
365f1b4000-365f3b4000 ---p 001b4000 fd:01 263128 /usr/lib64/libc-2.18.so
365f3b4000-365f3b8000 r--p 001b4000 fd:01 263128 /usr/lib64/libc-2.18.so
365f3b8000-365f3ba000 rw-p 001b8000 fd:01 263128 /usr/lib64/libc-2.18.so
365f3ba000-365f3bf000 rw-p 00000000 00:00 0
7f685162b000-7f6857b54000 r--p 00000000 fd:01 302750 /usr/lib/locale/locale-archive
7f6857b54000-7f6857b57000 rw-p 00000000 00:00 0
7f6857b6c000-7f6857b6d000 rw-p 00000000 00:00 0
7fffa6f09000-7fffa6f2a000 rw-p 00000000 00:00 0 [stack]
7fffa6ffe000-7fffa7000000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
我们看到/usr/bin/cat
有三个部分映射到0x400000
、0x60b000
和0x60c000
。
通过查看readelf -a /usr/bin/cat
的输出,您可以确定哪些部分对应于在这些地址加载的段。这留给读者作为练习:-)
全局变量和静态变量都在数据段。
malloc()
分配的内存位于堆。
函数中的自动变量都在堆栈中。
这是一个解释进程内存布局的网站:http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory/
它不是特定于C语言,但它显示了这些不同的内存区域是如何在进程内存中定位的。
所有"malloc"-ed变量/数组都在堆空间中分配内存,而所有其他变量都在堆栈中分配内存。
你应该可以在网上找到很多教程。