我最近一直在试验动态分配的数组。我得出结论,他们必须存储自己的大小才能释放记忆。
所以我在内存中用指针挖了一点,发现直接在6 * 4字节之前和直接在数组之后的1 * 4字节在重新编译时不会改变(不是随机垃圾)。
我将这些表示为unsigned int类型,并在win控制台中打印出来:
这是我得到的: (数组的内容介于 fdfdfdfd 表示中的uint之间)
所以我发现在数组的第一个元素之前的第三个unsigned int是以字节为单位的已分配内存的大小。
但我无法找到有关其余部分的任何信息。
问:有谁知道阵列内容的内存意味着什么,并且需要分享?
程序中使用的代码:
#include <iostream>
void show(unsigned long val[], int n)
{
using namespace std;
cout << "Array length: " << n <<endl;
cout << "hex: ";
for (int i = -6; i < n + 1; i++)
{
cout << hex << (*(val + i)) << "|";
}
cout << endl << "dec: ";
for (int i = -6; i < n + 1; i++)
{
cout << dec << (*(val + i)) << "|";
}
cout << endl;
}
int main()
{
using namespace std;
unsigned long *a = new unsigned long[15]{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 };
unsigned long *b = new unsigned long[15]{ 0 };
unsigned long *c = new unsigned long[17]{ 0 };
show(a, 15);
cout << endl;
show(b, 15);
cout << endl;
show(c, 17);
cout << endl;
cout << endl;
system("PAUSE");
delete[] a;
delete[] b;
delete[] c;
}
答案 0 :(得分:2)
这通常意味着您使用项目的调试配置和标准库的调试版本来执行实验。该版本的库使用一些预定义的位模式来标记每个分配的存储块的边界(&#34;没有人类的土地&#34;区域)。之后,它会检查这些位模式是否完好无损(例如,在delete[]
时刻)。如果他们没有,那就意味着有人写了超出内存块的边界。该库的调试版将发出有关该问题的诊断消息。
如果您在发布(优化)配置中使用标准库的发布(优化)版本编译测试程序,那么这些&#34;无人类的土地&#34;如果区域不会被创建,这些位模式将从内存中消失,相关的内存检查将从代码中消失。
另请注意,您观察到的内存布局通常特定于没有析构函数或具有普通析构函数的对象数组(这基本上是相同的)。在您的情况下,您使用普通unsigned long
。
一旦开始分配具有非平凡析构函数的对象数组,您将发现它不仅仅是实现存储的内存块大小(以字节为单位),而是数组的确切大小(元素中)通常也存储在那里。
答案 1 :(得分:-1)
“我得出结论,他们必须存储自己的大小才能释放记忆。”不,他们没有。
数组没有释放它的内存。你永远不会从new
/ malloc
获得数组。你得到一个指向你可以存储数组的内存的指针,但如果你忘记了你要求的大小,你就无法取回它。标准库通常也依赖于操作系统。
即使操作系统也不必记住它。有一些非常简单的内存管理实现,它基本上返回当前指向空闲内存的指针,并按指令请求的大小移动指针。 free
什么也没做,释放的记忆被遗忘了。
底线,内存管理是实现定义的,并且除了你得到的东西之外什么都不保证。编译器或操作系统可能会弄乱它,因此您需要查看特定于环境的文档。
您谈到的位模式通常用作安全防护,或用于调试。例如:When and why will an OS initialise memory to 0xCD, 0xDD, etc. on malloc/free/new/delete?