std::array 的堆分配

Posted

技术标签:

【中文标题】std::array 的堆分配【英文标题】:Heap allocation for std::array 【发布时间】:2019-07-07 15:40:27 【问题描述】:

根据this questionstd::array在栈上分配。然而,当它与Valgrind 一起使用时,它会显示一个堆分配,即使对于分配在堆栈上的元素也是如此。这是误报还是真的?

这里跟随两个mwe来说明行为。

无堆:

以下代码:

#include <array>

int main() 
    std::array<int*, 1> map;
    int value = 0;

产生预期的以下Valgrind 输出:

==14425== HEAP SUMMARY:
==14425==     in use at exit: 0 bytes in 0 blocks
==14425==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated

带堆:

但是,如果我尝试此代码:

#include <array>

int main() 
    std::array<int*, 1> map;
    int value = 0;

    map.at(0) = &value;

Valgrind给我

==14539== HEAP SUMMARY:
==14539==     in use at exit: 72,704 bytes in 1 blocks
==14539==   total heap usage: 1 allocs, 0 frees, 72,704 bytes allocated
==14539== 
==14539== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1
==14539==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14539==    by 0x4EC3EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==14539==    by 0x40106B9: call_init.part.0 (dl-init.c:72)
==14539==    by 0x40107CA: call_init (dl-init.c:30)
==14539==    by 0x40107CA: _dl_init (dl-init.c:120)
==14539==    by 0x4000C69: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so)
==14539== 

添加编译设置:

g++ -std=c++11 -O0 valgrind.cpp -o valgrind_build -I ../fake -I ../src
valgrind --track-origins=yes --dsymutil=yes --leak-check=full --show-leak-kinds=all ./valgrind_build

valgrind --version
valgrind-3.11.0

g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

【问题讨论】:

什么编译器和什么标志?无论如何,所有这些都应该在优化的构建中删除。 可能是误报,很难想出一个不会在数组中留下悬空指针(或使用堆分配)的 sn-p 用法 "根据这个问题,std::array 是在堆栈上分配的。" 不,它不是这么说的。它说的是std::array 不允许执行堆分配。如果你在堆上分配array 自身,那么数组将在堆上。 您的第二个示例看起来就像您在标准库中的全局对象中看到的一样(例如 cincout)。 非常相关:***.com/questions/31775034/… 【参考方案1】:

代码

map.at(0) = &value;

引入了边界检查,这可能又需要使用动态分配的东西(例如来自&lt;iostream&gt; 库)。

你可以再试一次

map[0] = &value;

不应用绑定检查。

【讨论】:

哇,没想到边界检查引入动态分配。但你是对的。 另一个不自动使用at()的原因。 我可以看到at() 使用的唯一动态分配内存是在抛出std::out_of_range 异常时。如果您不超出范围,则不会引发异常。那么,在这种情况下还有什么可以使用动态分配呢?即使没有抛出异常,也可能进行某种静态初始化? @remy “即使没有抛出异常,也可能进行某种静态初始化?”当然,这就是我的想法。

以上是关于std::array 的堆分配的主要内容,如果未能解决你的问题,请参考以下文章

分配给 gslice_array 会产生运行时错误

串的堆分配存储结构

线程特定的堆分配

在C中的堆上分配数组

用户 DLL/EXE 中的堆分配失败

对象向量是不是在 C++ 中的堆或堆栈上分配?