【问题标题】:C++ : memory management [duplicate]C ++:内存管理[重复]
【发布时间】:2014-04-05 18:29:23
【问题描述】:

我使用 new 分配了 5 个 int 空间,并尝试访问刚刚超出分配的边界 (array[size] = 2; )。理想情况下,它应该抛出一些错误,但事实并非如此。

int size = 5;
int* array = new int[size];

array[1] = 2;

//If I uncomment below line it gives me error

//array[size] = 2; 

cout << array[1] << endl;

// Why this is not an problem
cout << array[size] << endl;

delete[] array;

但是当我试图删除这个分配的空间时,它会显示这个错误。

*** glibc detected *** /home/workspace/PracticeC++/Debug/PracticeC++: free(): invalid next size (fast): 0x08add008 ***
PracticeC++: malloc.c:2451: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.

当我在评论 array[size] = 2; 行后尝试删除时,它工作正常。我无法理解这种奇怪的行为。根据我的理解 delete[] 运算符具有有关数组大小的信息,因此它不应超过该大小,并且此错误与我们尝试删除相同内存两次或未分配的情况有关我们。有人可以告诉我这个错误背后的原因。

【问题讨论】:

    标签: c++ c arrays pointers memory-management


    【解决方案1】:

    C 和 C++ 都不是边界检查,因为这会降低性能并需要额外的簿记数据。您的内存分配器可能会保存额外的信息,但仅限于其私人用途和私人格式。您本可以使用自己的/根本不使用它,因此它不可靠。
    违反不拥有的内存时遇到的未定义行为是程序员的责任。任何事情都可能发生。

    【讨论】:

    • 请看我的回答。我在@Deduplicator 回答之前写了它,我解释了为什么array[size] = 2 导致错误,提示:new(或malloc)存储分配的内存块的额外信息,它被delete(也是free)使用...
    • @rzymek:是的,这就是 practice 中发生的事情(使用特定的实现......),但是 UB 完美地解决了这个问题。
    • UB 是宽泛的术语。我从 OP question 中读到了一个要求解释为什么 array[size] = 2; 会导致问题的原因,不仅是为了对问题的一般看法,而且也许这只是我对这个问题的看法。我不想争论,这个答案也正确但不太具体。
    【解决方案2】:

    您这样做会覆盖一些重要信息array[size] = 2;

    malloc 函数(或 new 运算符)存储一些关于您在分配块之外分配的内存块的信息。当您释放内存时,delete 会使用这些信息。

    只有当您读/写不属于您的进程的内存时,您才会收到access violation 错误。当您写入由您的进程分配的内存时,您不会收到任何错误。 但是,您可能会在代码的其他地方遇到一些奇怪和意外的结果(就像您在此处的情况一样)。

    【讨论】:

      【解决方案3】:

      由于您使用的是指针,因此编译器没有真正的理由应该在这里抱怨。您基本上可以使指针变量指向操作系统允许的任何可能的内存位置。当您超出程序的内存分配时,将发生分段错误。

      如果您想避免无意中访问此类索引,则必须使用标准数组,或者更好的选择是使用 C++ 中提供的向量。

      【讨论】:

        【解决方案4】:

        在您分配的内存之外写入会导致未定义的行为。这意味着任何事情都可能发生,不同的实现可能会做不同的事情。在编译期间或运行时发生错误不是必需的。

        大概在您使用的实现的情况下,分配器将一些信息存储在与分配给您的内存块相邻的内存区域中。
        覆盖其中一些信息会导致尝试释放该内存时出现问题。
        但是你真的不能对程序在那个时候的行为做出任何假设。这就是为什么它被称为未定义行为。

        【讨论】:

          猜你喜欢
          • 2010-09-27
          • 1970-01-01
          • 1970-01-01
          • 2014-03-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多