我想继续将小的一/二/三字段C程序写入稍大的C项目。为此,我真的想让内存管理正确。现在我知道有类似的问题已被提出,但他们不能回答我的问题。我已经了解了一些理论并将其付诸实践。因此,我想展示我所知道或想要知道的内容,并纠正我或添加我想念的信息。
有堆栈,静态内存和堆
static int n; // goes to static memory, thread lifetime
char *array = malloc(256 * sizeof(*array)); // goes to heap, needs free(array)
func(int n) {
float f; // goes to stack, dies with func return
static double d; // thread lifetime again
}
静态内存无法溢出,因为它为所有静态变量设置, 但是堆和堆栈可能会溢出,在大多数情况下访问非分配内存时堆溢出,堆栈设置为~1MB Windows或~8MB Linux,如果用尽(我收到消息"核心转储" on我的Ubuntu用于为堆栈中图像的每个像素设置一个结构数组)
静态,堆栈和堆内存在每个范围内都是这样的吗? 我知道堆内存。但是全局非静态结构数组是否会进入堆栈?如果我在文件b中有一个没有main的静态数组怎么办? 继续使用静态内存吗?如果一个函数有一个具有初始值的局部静态变量,该怎么办?每次调用函数时都会初始化吗?并从堆栈中执行函数? 如何避免在具有长生命堆栈变量和大量程序的大型程序中耗尽堆栈?最重要的是,字符串文字在哪里?它们应该是指针而不是数组,但如果我更改指针原始字符串会发生什么?还有一件事:它总是困扰我如何编写像
这样的代码的不良做法 if(!strcmp(a, "comparethis")) do ...
或
fprintf(stderr, "There was a problem .... %d", something);
编辑
内存管理方面的差异在哪里?
char arr[3] = {'A', 'B', 'C'};
char arr[3] = "ABC";
char *arr = "ABC";
编辑结束
无论如何都要包含字符串文字,或者更确切地说是从文件或其他内容中读取它们?
最后,对不起,如果我的语法在这里和那里失败了,但这是以快速的方式写的。感谢阅读,请不要讨厌。如果我可以提出这么多问题,请概述我的错误,不要判断他们。我想改进和快速。
无论如何,祝你有个美好的一天。答案 0 :(得分:1)
有堆栈,静态内存和堆
不完全是。 C标准定义了自动存储,静态存储和动态存储。堆栈是自动存储的可能(实际上是常见的)实现,动态存储堆也是如此。这个定义作用于变量的生命周期:
malloc
(及相关)函数创建,并应由free
销毁。如果遵守这些规则,则可以自由地将对象物理存储到所需的位置。特别是,已知一些实现将自动数组存储在堆上并在块出口处自动销毁它们
静态内存不能溢出,因为它是为所有静态变量设置的
在MS / DOS时,小内存模型要求所有静态变量适合64 kbytes的单个段。如果您想要更多,则无法在该模式下进行编译。错误可能是单个编译单元中的编译错误导致错误,或者如果仅总大小超过64k则出现链接错误
堆栈设置为~1MB Windows或~8MB Linux
编译器选项允许在常用编译器上更改堆栈的大小
现在提出您的问题:
是否会在堆栈中使用全局非静态结构数组?
它可以依赖于实现,只要它在离开块时自动销毁,它可以存储在堆上
如果我在文件b中有一个没有main的静态数组怎么办?继续使用静态内存吗?
是的,它必须是静态的,翻译单元是否包含main
如果函数有一个具有初始值的局部静态变量,那该怎么办?每次调用函数时都会初始化吗?
因为它是静态的,所以它在程序开始时创建并初始化,并通过其他调用保持其值。它不会在以下呼叫中重新初始化
从堆栈中执行函数吗?
你在这里是什么意思?通用实现确实使用堆栈作为函数返回地址及其所有自动变量
如何避免在具有长寿命堆栈变量和大量变量的大型程序中耗尽堆栈?
您可以在编译时增加堆栈大小,或使用其他设计。例如,迭代算法比递归算法的堆栈消耗更少
最重要的是,字符串文字在哪里?
字符串litteral具有静态持续时间。某些实现将它们存储在只读段中,但不需要它。只是尝试修改字符串litteral是未定义的行为。
内存管理方面的差异在哪里?
char arr[3] = {'A', 'B', 'C'}; char arr[3] = "ABC"; char *arr = "ABC";
第一个和第二个都声明了一个由A
,B
和C
初始化的3个字符的非const数组,并且没有终止空值。
第三个是完全不同的:它声明了一个指向(空终止的)字符串的指针。这意味着arr[0] = 'X';
是未定义的行为,因为它修改了一个litteral。并sizeof(arr)
字符串的长度为sizeof(char *)
。
无论如何都要包含字符串文字,或者更确切地说是从文件或其他内容中读取它们?
我无法理解这个问题。程序内部有一个字符串文件。存储在文件中的字符串需要访问该文件。所以至少文件名必须是字符串文字。