c - 所有关于 C 内存管理

标签 c performance memory design-patterns projects

关闭。这个问题需要更多 focused .它目前不接受答案。












想改进这个问题?更新问题,使其仅关注一个问题 editing this post .

4年前关闭。




Improve this question




我想从编写小的一/二/三级 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,如果已用尽(我在我的 Ubuntu 上收到一条消息“core dumped”用于设置堆栈上图像的每个像素的结构数组)

  • 静态、堆栈和堆内存是否在每个范围内都表现得像这样?
    我知道堆内存可以。但是全局非静态结构数组是否在堆栈上?如果我在文件 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";
    

    编辑结束

    无论如何都包含字符串文字还是从文件中读取它们或者诸如此类的东西是好的吗?

    最后,对不起,如果我的语法在这里和那里失败了,但这是以快速的方式写的。感谢阅读,请不要讨厌。概述我的错误,不要评判它们,如果我能问那么多的话。我想提高和快速。

    不管怎样,祝你有美好的一天。

    最佳答案

    There is the stack, static memory and the heap



    不完全是。 C标准定义了自动存储、静态存储和动态存储。堆栈是自动存储的一种可能(实际上是常见的)实现,动态存储的堆也是如此。此定义作用于变量的生命周期:
  • 自动对象的生命受其包含 block
  • 约束
  • 静态对象在程序开始时就出现了,它们的生命延续到程序结束
  • 动态变量由 malloc 创建标准库中的(和相关的)函数,应由 free 销毁.

  • 如果遵守这些规则,则实现可以自由地将对象物理存储在它想要的位置。特别是,已知一些实现将自动数组存储在堆上并在 block 退出时自动销毁它们

    Static memory can't overflow since it's set for all static variables



    在 MS/DOS 时代,小内存模型要求所有静态变量都放在一个 64 KB 的段中。如果您想要更多,则无法在该模式下编译。该错误可能是单个编译单元中的编译错误导致该错误,或​​者如果仅总大小超过 64k 则为链接错误

    stack is set to ~1MB Windows or ~8MB Linux



    编译器选项允许更改常见编译器上的堆栈大小

    现在为您的问题:

    does a global non static array of structs go on the stack?



    它可以依赖于实现,只要它在离开 block 时自动销毁,它可以存储在堆上

    What if I have a static array in file b where there is no main? Goes on to static memory right?



    是的,它必须是静态的,翻译单元是否包含 main或不

    And what is if a function has a local static variable with initialized value? Is it initialized everytime i call the function?



    由于它是静态的,它在程序开始时创建和初始化,并通过其他调用保持其值。它不会在以下调用中重新初始化

    and do functions take from the stack?



    你在这里是什么意思?常见的实现确实使用堆栈作为函数返回地址及其所有自动变量

    How to avoid exhausting the stack in large programs with long lifed stack variables and plenty of them?



    您可以在编译时增加堆栈大小,或使用不同的设计。例如,迭代算法比递归算法消耗更少的堆栈

    And most of all, where do string literals go?



    字符串字面量具有静态持续时间。一些实现将它们存储在只读段中,但没有要求。简单地说,尝试修改字符串字面量是未定义的行为。

    Where is the difference in terms of memory management?

         char arr[3] = {'A', 'B', 'C'};
         char arr[3] = "ABC";
         char *arr = "ABC";
    


    第一个和第二个都声明了一个由 A 初始化的 3 个字符的非常量数组。 , BC ,并且没有终止的空值。

    第三个则完全不同:它声明了一个指向(以空结尾的)字符串litteral 的指针。这意味着 arr[0] = 'X';是未定义的行为,因为它修改了文字。和sizeof(arr)字符串的长度,但 sizeof(char *) .

    Is it good to include string literals anyway or rather read them from a file or whatnot?



    我无法理解这个问题。程序内部有一个字符串字面量可用。存储在文件中的字符串需要访问该文件。所以至少文件名必须是一个字符串字面量。

    关于c - 所有关于 C 内存管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48142032/

    相关文章:

    java - java程序运行60M或90M正常吗?

    c - Fisher Yates 算法在系统时间播种时在并行启动的程序中返回相同顺序的数字

    performance - 对多列的唯一约束是否有性能问题-Oracle

    ios - iPad 2 hd,会有内存问题吗?

    c# - 如何在 C# 中编写实体比较器(带有第一次尝试的示例代码)

    java - 比较 Querydsl、jOOQ、JEQUEL、activejdbc、iciql 和其他查询 DSL

    memory - 直接向内存写入数据和使用asm指令的区别

    c - REDIS 无法查询特定条件

    c - 我有一些关于如何将生成的数据保存在新字符串中的 for 循环中的问题

    c - 为函数参数指定寄存器?