std::array的堆分配

6
根据这个问题std::array是在堆栈上分配的。然而,当与Valgrind一起使用时,它向我显示了一个堆分配,即使对于在堆栈上分配的元素也是如此。这是一个误报还是真实情况?
下面是两个示例代码以说明这种行为。 没有堆: 以下代码:
#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;
}
< p > 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.

2
什么编译器和什么标志?这一切在优化构建中都应该被删除。 - Matthieu Brucher
1
可能是误报,很难想出一个使用这个片段的方法,不会让你在数组中留下悬空指针(或使用堆分配)。 - 463035818_is_not_a_number
10
根据这个问题,std::array 是分配在栈上的。不对,它并不是这个意思。它的意思是 std::array 不允许执行堆分配。如果你在堆上分配 array 本身,那么数组就会在堆上。 - Nicol Bolas
1
你的第二个例子看起来像标准库中全局对象(如 cincout)的样子。 - NathanOliver
非常相关:https://dev59.com/743da4cB1Zd3GeqP3Kow - NathanOliver
1个回答

10

这段代码

map.at(0) = &value;

介绍了边界检查,可能需要使用动态分配的内容(例如来自<iostream>库)。

您可以再次尝试

map[0] = &value;

不适用边界检查。


哇,没有想到边界检查会引入动态分配。但你是正确的。 - magu_
1
不自动使用 at() 的又一个原因。 - Pete Becker
我能够看出at()函数唯一使用动态分配内存的地方是在抛出std::out_of_range异常时。如果不越界,就不会抛出异常。那么,在这种情况下,还有什么其他可能使用动态分配的东西呢?也许是某种静态初始化,即使没有抛出异常? - Remy Lebeau
1
@remy "也许是某种静态初始化,即使异常没有被抛出?" 是的,这正是我所想的。 - πάντα ῥεῖ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接