4

可能重复:
如何在 malloc 之后获取内存块长度?

如果我有一个指针,是否可以知道分配了多少字节new?当我用谷歌搜索时,我找到了适用于 Windows:_msize()和 Mac:的解决方案malloc_size()。但对于 Linux 来说没有。

如果没有,有人知道为什么它对程序员隐藏吗?delete绝对应该知道这样的信息。

更新:

据我所知,如果我有这个代码:

 class A {   
   ~A() {}
   int m_a; 
 }; 
 class B : public A {
   ~B() {}
   int m_b; 
 };

 int main() {   A * b = new B();   delete b;   return 0; }

将调用 A 的析构函数,但仍将new释放所有分配的内存。这意味着它可以以某种方式计算,只知道指针。那么对程序员隐藏它的原因是什么?

4

6 回答 6

5

不幸的是,没有可移植new的方法来获取和分配的字节数malloc。出现这种情况的原因有很多:

  • 在某些平台上,delete什么free都不。因此,它们不需要存储尺寸信息。这在嵌入式平台中非常常见。它允许您使用为其他平台编写的 C 或 C++ 代码,只要您不进行过多分配即可。
  • 即使在更常见的平台上,系统分配的字节数也可能与您要求的不同。通常,您的分配将与更大的大小对齐 - 可能比您的原始请求大得多存储元数据也可能存储在一个非常慢的数据结构中——您不希望在时间关键的代码中获取锁并访问哈希表。

作为可移植语言,C 和 C++ 不能提供在每个平台上都不可用(或定义明确,或相当快)的特性。这就是为什么这在 C++ 上不可用。也就是说,你不需要这个 - C++ 提供std::vector,它跟踪你的分配大小,或者std::string它会为你处理所有这些细节。

于 2012-09-21T06:04:26.717 回答
3

new, malloc,calloc以及该语言中所有其他与堆相关的分配(是的,还有很多)将至少分配您请求的内存量。他们可能会分配更多(通常他们会分配更多)。

没有可移植的方式知道他们分配了多少。事实上,除非你确切地知道你正在使用什么堆管理器,否则根本没有办法。

您还需要从返回的指针(这是 malloc_size 在macs上返回的内容,可能是 _msize 在windows上返回的内容)与“从堆中取出”的实际内存中区分分配的内存,因为您可以从返回的指针安全访问分配(包括可能与您分配的内存块相邻或不相邻的簿记信息,并且对于相同大小的分配可能相同也可能不同)。

于 2012-09-21T07:27:15.747 回答
1

问:那么我可以查询 malloc 包以找出分配的块有多大吗?

A:不幸的是,没有标准或可移植的方式。(一些编译器提供非标准扩展。)如果您需要知道,您必须自己跟踪它。

常见问题

于 2012-09-21T05:45:57.483 回答
1

运算符所做的new是调用构造函数,因此分配的大小取决于您正在调用其构造函数的类型。

例如

class A
{
private:
    int* x;
public:
    A() { x = new int [100]; }
};

将分配sizeof(int) * 100,但您不知道 A 的实现是否对您隐藏。

如果你自己表演:

int * x = new int [100];

然后你知道你分配了多少因为可以访问sizeof(primitive).

此外,delete操作员调用析构函数,因此对于复杂对象,它再次不需要知道分配内存的大小,因为完全正确地释放内存的责任完全委托给了程序员。

所以这里没有直接的答案。

于 2012-09-21T05:51:37.233 回答
1

除了上面的答案:在某些情况下,必须分配和释放的大小在编译时是已知的,在某处记录大小将是一个完整的内存腰围。

在静态类型等于动态类型的情况下,要释放的内存可以由类型决定。

在静态类型不等于动态类型的情况下,删除的对象类必须具有虚拟析构函数。此析构函数可用于释放正确大小的内存。

在分配数组时,数组的大小通常以依赖于实现的方式附加到该数组,并且要释放的大小可以由元素的类型和数组的大小来确定。

于 2012-09-21T07:42:18.000 回答
0
 X x=new X()

这取决于类的大小,即类包含的变量数量

int x = new int [100];

这取决于你要分配多少元素。假设,int 需要 2 个字节,那么这里需要 200 个字节。
简而言之,我们可以说,它取决于数据类型,您使用新运算符

于 2012-09-21T05:59:30.710 回答