所以,我继续学习C.我有一些有趣的问题。
如果我没有把错误放在堆上,我必须使用malloc
等。
但是char * str
呢?
在str
位于哪个内存段?
我读到它将被放在.bss段上。(这就是为什么你不能在C中改变字符串)。它是否正确?或者它会被堆叠?
如果是,为什么在程序结束时不需要释放这些内存? 还有每个函数的内存段代码?换句话说,指向函数的指针将指向哪个段? 谢谢您的帮助! 只是想在C中更好地理解内存管理。
答案 0 :(得分:4)
如果您只是说char * str
,则不会分配数组的内存,只有指针本身的内存。您需要手动为字符串分配内存,可能在堆上,也可能手动释放它。
“你无法在C中更改字符串”是错误的。您不能更改字符串常量,并且字符串常量分配在.rodata
(只读部分)之类的内容中。与任何其他代码一样,函数代码与.text
。
答案 1 :(得分:4)
如果在函数中放置定义char *str;
,那么它是“指向 - char
”类型的自动变量。
它位于堆栈中,当函数返回时,堆栈的那一部分变为未使用(编译器通过发出代码来根据需要移动堆栈指针来处理此问题)。从理论上讲,堆栈的存在纯粹是一个实现细节,实际上C总是有一个调用堆栈,几乎所有的实现都或多或少地以相同的方式管理,然而它实际上是被管理的,存储自动变量的内存是可能被称为“堆栈”。
如果将定义char *str;
放在任何函数之外,那么它是一个具有静态存储持续时间的全局变量。
它存储在读写数据段中,并在程序退出时变为未使用(可能是OS为您处理此问题,尽管它原则上可能是编译器发出的代码)。由于它是零初始化的(假设一个架构,其中空指针由所有位零表示)是,它可以进入bss段,这专门用于具有静态存储持续时间的零初始化读写对象。同样,存储静态持续时间对象的详细信息取决于实现,但同样,这也是通常的完成方式。
这与字符串文字无法修改有任何关系,因为你没有定义字符串(更不用说使用字符串文字了)。你已经定义了一个指针,它可以指向一个字符串但是(还)没有这样做。
答案 2 :(得分:2)
在C中,所有局部变量都将放在堆栈中。变量str
是一个字符指针。它包含一个内存地址。在堆栈上只会有一个名为str
的指针。
char * str;
这将使用指针大小(在32/64位上为4或8个字节)在堆栈上分配内存。
str = malloc(1024);
malloc
在堆上分配1024字节,并返回指向该内存区域的第一个字节的指针。该指针保存在堆栈中的str
中。
当函数(str
是局部变量)返回时,您的变量str
将被释放。
指向的内存区域str
将不会自动释放。您需要使用free(str)
手动执行此操作。
字符串可以修改!但不是恒定的文字:
char string[4] = "foo";
string[0] = 'F'; //will work
char * stringconst = "foo";
stringconst[0] = 'F'; // this will segfault
以上操作不起作用,因为“foo”将被放置(希望)在只读内存区域。
答案 3 :(得分:2)
我认为你已经混淆了指针以及它们指向的内容。拿这个:
char *str = "Hello";
如果在文件范围声明了,那么str
是静态分配的指针。它指向的字符串是完全独立的。您可以str
指向任何内容。
如果它在函数中声明,那么str
是在堆栈上分配的指针。文字是独立的。
事实上,如果你有这两行:
char *str1 = "Hello";
char *str2 = "Hello";
编译器可以自由地指向内存中的相同地址。
无论指针如何,都会静态分配字符串文字,并且它(通常)放在初始化的只读数据段中。
还要记住,堆,堆栈和段的所有概念都与实现完全相关,而不是语言。
答案 4 :(得分:1)
我在阅读类似问题的答案时发现了两个链接。这些可能会帮助您更好地理解这个问题。
答案 5 :(得分:0)
在C中,我们可以通过字符数组或字符指针来引用字符串。
案例1:如果字符串被称为字符数组:
char[] = "storage of strings";
如果上述声明是GLOBAL,那么它存储在DATA段中,否则将存储在STACK段中。
案例2:如果字符串由字符指针引用,并且在运行时分配内存,即使用malloc,calloc。
char *str = (char *)malloc(sizeof(char)*size);
在这种情况下,内存是从HEAP段分配的。
案例3:如果字符串由字符指针引用,则字符串值直接分配给char指针。
char *str = "storage of strings"
在这种情况下,它将存储在DATA段中。就像字符串文字在数据段中分配了一个内存,并且该字符串文字的地址被分配给str变量。
PS:在运行时分配的每个内存(HEAP Segment)都需要在程序本身中释放。因此,如果您使用malloc,calloc或任何在运行时分配内存的函数,则需要使用free()。