C ++:内存管理[重复]

Posted

技术标签:

【中文标题】C ++:内存管理[重复]【英文标题】:C++ : memory management [duplicate] 【发布时间】: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[] 运算符具有有关数组大小的信息,因此它不应超过该大小,并且此错误与我们尝试删除相同内存两次或未分配的情况有关我们。有人可以告诉我这个错误背后的原因。

【问题讨论】:

【参考方案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】:

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

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

【讨论】:

以上是关于C ++:内存管理[重复]的主要内容,如果未能解决你的问题,请参考以下文章

C语言进阶:动态内存管理

c语言 学生管理系统

C/C++内存管理详解

C/C++内存管理

C++03_内存管理

C/C++内存管理