我目前正在学习Linux进程地址空间,并且不确定这些C变量在进程地址空间中的对应位置。
我知道调用一个函数时,会创建一个新框架,其中将包含局部变量和其他函数调用等。
我不确定框架中的指针是什么
我有这个功能:
int main(){
char *pointer1 = NULL;
char *pointer2 = (void *)0xDDDDDDDD;
pointer1 = malloc(80);
strcpy(pointer1, "Testing..");
return(0);
}
调用main时,将创建一个新框架。
变量被初始化。
我不确定这些是指针,在哪里:
*pointer1
对应于进程地址空间中的数据还是文本部分?
*pointer2
对应于进程地址空间中的数据还是文本部分?
NULL
和0xDDDDDDDD
是否属于数据或文本部分?
自pointer1 = malloc(80)
起,它属于堆栈部分吗?
答案 0 :(得分:0)
首先应该注意,C规范实际上并不要求将局部变量存储在堆栈中,它根本没有指定 automatic 变量的位置。
话虽这么说,变量pointer1
和pointer2
本身的存储很可能由编译器放在堆栈上。当调用main
函数时,它们的内存将成为编译器创建的堆栈框架的一部分。
继续,在类似现代PC的系统上,指针实际上只不过是一个简单的无符号整数,其值就是它所指向的地址。用于初始化的值(NULL
和0xDDDDDDDD
)只是简单的整数值。初始化与普通的int
变量相同。因此,用于初始化的值实际上并不以“数据”形式存在,而是可以直接在机器代码中编码,并因此存储在“文本”(代码)段中。
最后,对于动态分配,它不会更改pointer1
的存储位置。它只是为pointer1
分配一个新值是什么。分配的内存位于“堆”上,该“堆”与任何程序节均独立(即不在代码,数据或堆栈段中)。
答案 1 :(得分:0)
正如一些程序员伙计所说,C规范未声明必须放置自动变量的区域。但是通常编译器会增加堆栈以将其容纳在此处。但是,它们可能以.data区域结尾,并且如果例如被定义为static char *pointer1
,它们将结束。
初始化值在程序区域中可能存在也可能不存在。在您的情况下,由于值的类型为int
,因此,如果可以使用带有适当内联运算符的指令,则大多数体系结构都将内联初始化作为适当的机器指令进行内联。例如,在x86_64中,将发出单个mov
/ movq
操作,以将0(NULL)或另一个int放入堆栈中的适当内存位置。
但是,用全局作用域初始化的变量,例如static char string[40] = "Hello world"
或其他初始化的全局变量最终在.data
区域上占据了空间。编译器可以改为在.bss
区域中放置已声明但未定义的全局范围的变量。
问题由于指针1 = malloc(80),它属于堆栈部分吗?定义不明确,因为它包含两件事。
值pointer1
是将保存在&pointer1
处的值。考虑到以上考虑,编译器可能会将其放在堆栈中的地址。
malloc(80)
的结果是一个值,该值引用堆上的一个区域(一个不同的区域),该区域在映射的程序空间之外动态分配。
在Linux上,调用malloc
的结果甚至可能创建一个新的以NULL为后盾的内存区域(即,不是永久存储在文件中的过渡区域;尽管它可以被内核交换)。>
从本质上讲,您可以想到malloc(80)的行为,就像(不考虑free(),所以这是一个过分的简化):
int space_left = 0; void *last_mapping = NULL;
void *malloc(int req) {
void *result;
if (space_left < req) {
last_mapping = mmap(NULL, MALLOC_CHUNK_LENGTH, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
space_left = MALLOC_CHUNK_LENGTH;
}
space_left -= req;
result = last_mapping;
last_mapping += req;
return result;
}
使用MAP_PRIVATE调用malloc
和mmap
之间的巨大区别是mmap是Linux系统调用,它必须进行内核上下文切换,分配新的内存映射并为每个重置MMU层。分配内存块,而malloc可以更智能,并使用单个大区域作为“堆”,并在堆初始化之后在用户空间中管理不同的malloc和free(直到堆空间用完为止,在那里它可能必须管理多个堆) )。
答案 2 :(得分:-1)
您最后一个疑问的部分,即“因为指标1 = malloc(80),它属于堆栈部分吗?”,我可以告诉您
在C语言中,使用某些标准库函数从堆分配动态内存。两个关键的动态内存函数是malloc()和free()。
malloc()函数采用单个参数,该参数是请求的内存区域的大小(以字节为单位)。它返回一个指向已分配内存的指针。如果分配失败,则返回NULL。标准库函数的原型是这样的:
void *malloc(size_t size);
free()函数采用malloc()返回的指针,并取消分配内存。没有返回成功或失败的指示。函数原型如下:
void free(void *pointer);
您可以参考文档 https://www.design-reuse.com/articles/25090/dynamic-memory-allocation-fragmentation-c.html