为什么这个程序不消耗内存?
delete []
实际上做了什么让我很困扰,所以我只是尝试了一些代码,结果令我震惊
测试 #1:
int main()
{
int *d;
while(true)
{
d = new int[10];
delete []d;
}
}
程序根本不消耗任何内存,正如预期的那样。
测试 #2:
int main()
{
int *d;
while(true)
{
d = new int[10];
delete [](d + 5);
}
}
虽然在每个循环中应该至少保留 20 个字节(对于它在数组开头保留的 5 个整数),但这些字节不会被删除,但该程序也不会消耗任何内存!
测试 #3:
int main()
{
int *d;
while(true)
{
d = new int[10];
delete []d;
*d=1;
}
}
这正如预期的那样导致了访问冲突(似乎所有内存在 delete []d
之后都被删除了)。
测试#4:
int main()
{
int *d;
while(true)
{
d = new int[10];
delete [](d+5);
*d=1;
}
}
这是最令人惊奇的,虽然虽然不消耗任何内存,但程序也不会产生任何访问冲突,我只是想知道 *d 在哪里存储它的数据?
(顺便说一句,所有程序都是使用无优化编译的!)
现在的主要问题是:
如果我分配了一个数组并且我已经完成了其中一半的工作,我能不能有机会释放那一半并保留另一半呢?一半?
It's bothering me what delete []
actually does, so I just tried some code and I was shocked with the results
Test #1:
int main()
{
int *d;
while(true)
{
d = new int[10];
delete []d;
}
}
The program doesn't consume any memory at all, as expected.
Test #2:
int main()
{
int *d;
while(true)
{
d = new int[10];
delete [](d + 5);
}
}
Though in every loop there should be at least 20 bytes (for the five ints it reserves at the beginning of array) reserved which are not deleted this program also doesn't consume any memory!
Test #3:
int main()
{
int *d;
while(true)
{
d = new int[10];
delete []d;
*d=1;
}
}
This one caused access violation as expected (seems all the memory is deleted after delete []d
).
Test #4:
int main()
{
int *d;
while(true)
{
d = new int[10];
delete [](d+5);
*d=1;
}
}
This one was the most amazing, though the while doesn't consume any memory the program doesn't produce any access violations either, I'm just wondering where *d is storing it's data?
(By the way all programs are compiled using no-optimization!)
Now the main question :
What if I allocated an array and I've done working with half of it, can't I by any chance release that half and keep the other half?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
你不应该担心
delete[]
实际做了什么。出于所有意图和目的,它是一个黑匣子,具有有关如何正确使用它的某些规则。您唯一需要担心它实际需要做什么的时候是您正在编写编译器或 C++ 运行时(例如操作系统等)。关于那些“如何正确使用它的某些规则”,测试#2 和 #4 调用未定义的行为:
“未定义的行为”意味着任何事情都可能发生,包括您刚才描述的行为。
测试 #2 和 #4 中的这些表达式违反了 5.3.5/2,并将导致未定义的行为(测试 #3 也会导致未定义的行为,但原因不同)。
delete[]
行违反了 5.3.5/2,因为您传递给delete[]
的指针值与new 为您提供的值不同int[]
。因此,如果
new int[]
命令为您提供0xA01D2CE9
并且您将0xA01D2CE9 + 5
传递给delete[]
,你不可能推理或预测会发生什么,因为你已经违反了语言的规则。实际发生的情况取决于编译器和/或操作系统如何处理new[]
和delete[]
。这可能包括从没有发生任何错误到系统完全崩溃,以及介于两者之间的任何情况。换句话说,只是不要编写诸如
delete [](d + 5);
之类的内容。You're not supposed to worry about what
delete[]
actually does. It's for all intents and purposes a black box with certain rules on how to use it properly. The only time you need to worry about what it needs to actually do is if you're writing a compiler or a C++ runtime (e.g. operating systems, etc.)With respect to those "certain rules on how to use it properly", Test #2 and #4 invokes undefined behavior:
"Undefined Behavior" means that anything can happen, including the behavior you just described.
These expressions that you have in Tests #2 and #4 are in violation of 5.3.5/2 and will cause undefined behavior (Test #3 will also cause undefined behavior, but for a different reason).
The
delete[]
line violates 5.3.5/2 because pointer value you pass todelete[]
wasn't the same value that was given to you fromnew int[]
.So if the
new int[]
command gives you0xA01D2CE9
and you pass in0xA01D2CE9 + 5
todelete[]
, you cannot possibly reason about or predict what will happen because you have broken the rules of the language. What will actually happen will be dependent on how the compiler and/or the operating system handlesnew[]
anddelete[]
. That can range from nothing wrong happening to completely crashing your system, and everywhere in between.In other words, just don't write things like
delete [](d + 5);
.当您说“不消耗任何内存”时,您是在谈论“任务管理器”风格的性能监视器内部查看时的情况吗?因为如果是这样,40 字节将不会显示为“内存使用量”...您将必须分配更多内存才能使其显示在大多数标准进程性能监视器中。
When you say "doesn't consume any memory", are you talking about when viewed inside of a "task-manager" style performance monitor? Because if-so, 40-bytes will not show up as "memory usage" ... you're going to have to allocate a lot more memory for it to show up in most standard process performance monitors.
(来自您的测试#2)绝对是您不应该做的事情,如果不是段错误,这会损坏内存。它实际上在我的平台上出现了段错误。
测试的结果将取决于很多因素,其中包括运行这些测试的平台、new/delete 的内部结构等。
(from your test #2) is definitively something you should not do, this will corrupt the memory if not segfault. It actually segfaults on my platform.
The outcome of your tests will depend on many things, among other things the platform your run these tests on, the internals of
new/delete
etc.听起来您希望这仅释放
new int[10]
分配的部分内存。事实并非如此,它会导致未定义的行为并可能导致任何事情发生。
在某些内存管理器上,如果您要求它们通过传递指针来释放块,如果您不将指针传递到块的开头,那么它们可能会释放包含该指针的整个块你通过了。您的情况很可能会发生这种情况。
另一个考虑因素是 new int[10] 不会初始化分配的内存,因此操作系统只需分配一些地址空间,不需要使用任何物理存储来支持分配。这意味着,即使您在没有任何
delete[]
的情况下在循环中调用new int[10]
,您也可能会在许多内存监控工具中看到内存使用量没有上升,甚至高达当您耗尽逻辑bvg地址空间时,new[]
抛出std::bad_alloc
异常的点。 (一次仅分配 10 个字节可能需要一些时间。)It sounds like you are expecting this to free just part of the memory allocated by
new int[10]
.This is not the case, it causes undefined behavior and could cause anything to happen.
On some memory managers, if you ask them to free a block by passing a pointer, if you don't pass a pointer to the beginning of the block then they may free the entire block that contains the pointer that you pass. This may well be happening in your case.
Another consideration is that
new int[10]
does not initialize the memory allocated so the operating system can just allocate some address space and doesn't need to back the allocation with any physical storage. This means that even if you callnew int[10]
in a loop without anydelete[]
you may see no rising memory usage in many memory monitoring tools, even up to the point whennew[]
throws astd::bad_alloc
exception when you exhaust the logicalbvg address space. (This is likely to take some time just allocating 10 bytes at a time.)您是否在发布版本下运行这些测试?您看过生成的汇编指令吗?您如何测量内存消耗?您只分配了 40 个字节,然后立即清除它。
此外,执行诸如
delete [](d + 5)
之类的操作会调用未定义的行为。您需要传入operator new
返回的指针,以便delete
正常工作。Are you running these tests under a release build? Have you looked at the generated assembly instructions? How are you measuring memory consumption? You're ony allocating 40 bytes and then immediately clearing it.
Also, doing something like
delete [](d + 5)
is invoking undefined behavior. You need to pass in the pointer returned byoperator new
in order fordelete
to work correctly.