【发布时间】:2019-09-19 10:04:01
【问题描述】:
我正在尝试跟踪在我的开发过程中分配了多少内存。跟踪分配很容易,因为void *operator new (size_t) 和void *operator new[](size_t) 的过载允许跟踪分配了多少。
使用 C++ one can resort to a technique of over-allocating memory to store the size of the allocation
从 C++14 开始,有相应的 void operator delete(void*p, size_t size) 和 void operator delete[](void*p, size_t size) 应该允许准确地说明每次取消分配(除了不完整类型的删除,然后留给实现)。
但是,尽管第一个版本由 g++ 调用,其中调用了删除单个对象,但我还没有找到调用第二个的单个编译器。这是我的测试代码:
#include <iostream>
size_t currentAlloc;
void * operator new(size_t size)
{
currentAlloc += size;
std::cout << "1\n";
return malloc(size);
}
void *operator new[](size_t size)
{
std::cout << "3\n";
currentAlloc += size;
return malloc(size);
}
void operator delete(void *p) noexcept
{
std::cout << "Unsized delete\n";
free(p);
}
void operator delete(void*p, size_t size) noexcept
{
std::cout << "Sized delete " << size << '\n';
currentAlloc -= size;
free(p);
}
void operator delete[](void *p) noexcept
{
std::cout << "Unsized array delete\n";
free(p);
}
void operator delete[](void*p, std::size_t size) noexcept
{
std::cout << "Sized array delete " << size << '\n';
currentAlloc -= size;
free(p);
}
int main() {
int *n1 = new int();
delete n1;
int *n2 = new int[10];
delete[] n2;
std::cout << "Still allocated: " << currentAlloc << std::endl;
}
使用g++ -std=c++14 test.C 或clang++ -std=c++14 test.C 编译。 g++ 的输出结果:
1
大小删除 4
3
未调整大小的数组删除
仍分配:40
我期望为第二个delete 调用大小数组删除,最后打印的值为 0 而不是 40。clang++ 不会调用任何大小的取消分配,英特尔编译器也不会。
我的代码有什么不正确的吗?我误解了标准吗?还是g++和clang++都不符合标准?
【问题讨论】:
-
您似乎假设
void operator delete[](void *p) noexcept中的free(p);不会释放整个数组。 -
在 c++ 中使用
malloc()和free()优于new()和delete()的任何原因? -
@FrançoisAndrieux 我不知道你是怎么想的?我没有对免费做出任何假设。我只是想跟踪我的代码在任何时间点当前分配了多少内存。
-
@Michel 您只在几个运营商中跟踪它。例如
operator delete(void*)可能会释放内存,但您没有在那里跟踪它。 -
/Zc:sizedDealloc在这里没有任何区别,来自 MSDN 的关键引用是“当编译器无法确定被释放对象的大小时调用单参数版本”,编译器无法从原始指针轻松确定数组的大小。