6

According to this question std::array is allocated on the stack. However when using it together with Valgrind it shows me a heap allocation, even for elements which are allocated on the stack. Is this a false positive or real?

Here follow two mwe to illustrate the behavior.

No heap:

The following code:

#include <array>

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

Produces the expected following Valgrind output:

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

With heap:

However if I try this code:

#include <array>

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

    map.at(0) = &value;
}

Valgrind gives me

==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== 

Added compile settings:

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.
5
  • 2
    What compiler and what flags? All this should be removed in an optimized build anyway. Commented Feb 13, 2019 at 17:47
  • 1
    could be a false positive, its hard to come up with a usage of this snippet that wont leave you with a dangling pointer in the array (or using heap allocation) Commented Feb 13, 2019 at 17:48
  • 10
    "According to this question std::array is allocated on the stack." No, that's not what it says. What it says is that std::array is not allowed to perform heap allocation. If you allocate array itself on the heap, then the array will be on the heap. Commented Feb 13, 2019 at 17:48
  • 1
    Your second example look like what you'd see from the global object in the standard library (like cin and cout). Commented Feb 13, 2019 at 17:48
  • very related: stackoverflow.com/questions/31775034/… Commented Feb 13, 2019 at 17:52

1 Answer 1

10

The code

map.at(0) = &value;

introduces bounds checking, which might in turn need to use stuff allocated dynamically (e.g. from the <iostream> library).

You may try again with

map[0] = &value;

which doesn't apply bound checks.

Sign up to request clarification or add additional context in comments.

4 Comments

Wow, didn't think about bound checking introducing dynamic allocation. But you are correct.
Yet another reason to not automatically use at().
The only dynamically allocated memory I could see at() using is when throwing a std::out_of_range exception. If you don't go out of bounds, no exception is thrown. So, what else could be using dynamic allocation in this case? Maybe some kind of static initialization even if the exception is not thrown?
@remy "Maybe some kind of static initialization even if the exception is not thrown?" Sure, that is what I was thinking of.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.