【问题标题】:How much memory is reserved when i declare a string?声明字符串时保留多少内存?
【发布时间】:2010-04-07 04:43:01
【问题描述】:

就内存而言,当我声明如下内容时,究竟会发生什么: 字符 arr[4];

为 arr 保留了多少字节?

当我在 arr 中“strcpy”一个长度为 4 的字符串时,如何容纳空字符串?

我正在编写一个套接字程序,当我尝试在 arr[4](即第 5 个内存位置)处添加 NULL 后缀时,我最终替换了程序的其他一些变量的值(溢出)并进入了一个大混乱。

关于编译器(我使用的是 gcc)如何管理内存的任何描述?

【问题讨论】:

  • 大小应该是4chars+\0 => arr[5]

标签: c memory-management


【解决方案1】:

sizeof(arr) 字节被保存*(加上编译器想要放在它周围的任何填充,尽管这不是 for 数组本身)。在具有堆栈的实现中,这仅意味着将堆栈指针sizeof(arr) 向下移动字节。 (这就是存储的来源。这也是自动分配速度快的原因。)

'\0' 不适用。如果您将“abcd”复制到其中,则会出现缓冲区溢出,因为这总共占用 5 个字节,但您只有 4 个。您输入未定义的行为区域,任何事情都可能发生。

实际上,您迟早会破坏堆栈并崩溃,或者体验您所做的并覆盖附近的变量(因为它们也像数组一样被分配。)但是没有人能确定会发生什么,因为它是未定义。

* 这是sizeof(char) * 4sizeof(char) 总是 1,所以是 4 个字节。

【讨论】:

  • +1 用于明确指出 sizeof(char) 始终等于 1。
【解决方案2】:

究竟发生了什么,就 记忆,当我声明类似: 字符 arr[4];

4 * sizeof(char) 字节的堆栈内存是为字符串保留的。

我如何容纳空字符串 'strcpy' arr 中长度为 4 的字符串?

你不能。您只能有 3 个字符,第 4 个字符(即 arr[3])应该是 '\0' 字符以获得正确的字符串。

当我尝试在 arr[4] 处添加 NULL 后缀时

当您访问无效的内存位置时,该行为将未定义。在最好的情况下,您的程序会立即崩溃,但它可能会破坏堆栈并在稍后的时间点崩溃。

【讨论】:

    【解决方案3】:

    在 C 中,您要求的是--通常--正是您得到的。 char arr[4] 正好是 4 个字节。

    但是引号中的任何内容都在末尾添加了一个“隐藏”空值,因此char arr[] = "oops"; 保留了 5 个字节。

    因此,如果你这样做:

    char arr[4];
    strcpy(arr, "oops");
    

    ...当您只为 4 保留空间时,您将复制 5 个字节 (o o p s \0)。接下来发生的任何事情都是不可预测的,而且通常是灾难性的。

    【讨论】:

    • 请注意,虽然char arr[] = "oops"; 为尾随的 NUL 保留了额外的字节,但可以通过使用 char arr[4] = "oops"; 来抑制它。但是,如果没有 NUL,它当然不能作为 C 字符串工作...... =)
    • 次要:您应该使用NUL'\0' 来引用终止符,而不是NULL(空指针常量)。
    • @Arkku:我不知道编译器会用它做什么(我怀疑行为是未定义的)。 @jamesdlin:已修复。
    • char arr[4] = "oops"; 在标准 C 中定义;它相当于char arr[4] = {'o','o','p','s'};。见the C FAQ
    【解决方案4】:

    当您定义像 char arr[4] 这样的变量时,它会为该变量保留 4 个字节。正如您所发现的,超出该点的内容会导致标准所称的“未定义行为”——委婉说法是“你搞砸了——不要那样做”。

    这样的内存管理非常简单:如果它是全局的,它会被分配到全局内存空间中。如果它是本地的,它会通过从堆栈指针中减去适当的数量来分配到堆栈上。当您返回时,堆栈指针会恢复,因此它们不再存在(当您调用另一个函数时,通常会被该函数的参数和局部变量覆盖)。

    【讨论】:

      【解决方案5】:

      当您进行char arr[4]; 之类的声明时,编译器会分配您要求的字节数,即四个。编译器可能分配额外的内存以适应高效的内存访问,但通常你得到的正是你所要求的。

      如果您随后在同一个函数中声明另一个变量,则该变量通常会在内存中跟随arr,除非编译器再次进行某些优化。因此,如果您尝试写入arr,但写入的字符比实际分配给arr 的字符多,那么您可以覆盖堆栈上的其他变量。

      这并不是 gcc 的真正功能。所有 C 编译器的工作方式基本相同。

      【讨论】:

        猜你喜欢
        • 2021-01-26
        • 2018-08-12
        • 2014-05-22
        • 1970-01-01
        • 1970-01-01
        • 2013-11-18
        • 2011-07-01
        • 1970-01-01
        • 2021-09-08
        相关资源
        最近更新 更多