C++:内存管理

C++ : memory management

本文关键字:管理 内存 C++      更新时间:2023-10-16

我已经使用 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.

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

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

通过执行此操作来覆盖一些关键信息array[size] = 2;

malloc 函数(或新运算符)存储有关您分配的内存块的一些信息,这些信息刚好超出分配的块。当您释放内存时,delete会使用这些信息。

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

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

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

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

据推测,在您正在使用的实现中,分配器将某些信息存储在分配给您的内存块旁边的内存区域中。
覆盖其中一些信息会导致尝试释放该内存时出现问题。
但是你真的不能对程序在这一点上的行为做出任何假设。这就是为什么它被称为未定义的行为。