0

I did a small amount of research on the allocation of std::array and std::vector

My current (simplistic) understanding is:

std::vector is an object that holds a pointer to its array/collection/buffer of values

std::array is an object that holds its array/collection/buffer

A very incorrect but effective demonstration of this is

printf("%llu\n", sizeof(*new std::vector<uint64_t>(10)));
printf("%llu\n", sizeof(*new std::array<uint64_t, 10>));

24 (consisting of vector things)
80 (consisting of uint64_t[10])

Defining a variable defines it on the stack

Defining an std::array defines/allocates it's array/collection/buffer on the stack - so why doesn't std::array<uint64_t, 1000000000000000> array (1 PB) cause a stack overflow?

Why doesn't defining an object that exceeds the stack size on the stack not cause a segfault?

Adam W
  • 317
  • 1
  • 3
  • 15
  • 1
    If you `new` something, it is not on the stack, even if it is `std::array`. And deallocating immediately from `new` without assigning to a variable is a fast way to leak memory. – Cory Kramer Oct 29 '17 at 14:04
  • of course - in the printf I deference it. consider `std::array array;` within a function - calling the default constructor implicitly - what is in the question about is just for proof of concept/explanation – Adam W Oct 29 '17 at 14:06
  • Read about memory swapping. Also, check really memory usage in your case. You can use the ProcExplorer on windows or top/htop on linux. – voltento Oct 29 '17 at 14:10
  • @voltento I am familiar with memory swapping - my question is why doesn't defining an object that exceeds the stack size on the stack not cause a stack overflow? – Adam W Oct 29 '17 at 14:12
  • "in the printf I deference it" dereferencing will not create a temporary by itself ( at most a prvalue ) – Massimiliano Janes Oct 29 '17 at 14:12
  • @AdamWatson In this case, like it was said above, you allocate memory on a heap, because u use 'new'. – voltento Oct 29 '17 at 14:13
  • C++ has no standard concept of a stack (at least in this context). And in your example nothing is automatically allocated, what exactly are you asking here?... – George Oct 29 '17 at 14:13
  • `void foo() { std::array array; }` - array is defined on the stack here correct? 80 bytes exists on the stack and array is not just a pointer to a `std::array` correct? @voltento - thus, defining an `std::array` of size infinity (or whatever) should through a stack overflow no? – Adam W Oct 29 '17 at 14:16
  • 1
    @AdamWatson It seems that you are wrong with that. When I read http://en.cppreference.com/w/cpp/container/array I see, that when you swap a vector with one another, iterators are still points to the same item in the same vector. So, it looks like vector data located in heap. Also, I read http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf and saw for memory allocation an allocator is used. – voltento Oct 29 '17 at 14:28
  • In other words, if you can't find something in the standard documentation so, this opportunities and features may be implemented in a different way for different compilers. – voltento Oct 29 '17 at 14:30
  • 1
    gotcha @voltento - good to know - ive learnt a lot. thanks! – Adam W Oct 29 '17 at 14:31

1 Answers1

1
printf("%llu\n", sizeof(*new std::vector<uint64_t>(10)));
printf("%llu\n", sizeof(*new std::array<uint64_t, 10>));

First, Neither an object of std::vector<uint64_t> nor std::array<uint64_t, 10> is created here because that expression appears in an Unevaluated Contexet.

Defining an std::array defines/allocates it's array/collection/buffer on the stack - so why doesn't std::array<uint64_t, 1000000000000000> array (1 PB) cause a stack overflow?

you probably still did that in an unevaluated context. Demo.

However, in evaluated contexts such as:

int main(){
    std::array<uint64_t, 1000000000000000> arr;
}

Now, you are likely to get a segfault depending on your environment. You should also know that, the compiler may optimize the code away, (since there's no access to the elements).

Secondly, your code snippet - is not the way to estimate the memory consumed by a container with elements. For std::array we may make assumptions and accept a variant of your code, but certainly not std::vector.

WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
  • 1
    ah - segmentation fault not stack overflow. i see. segfault is the result - stack overflow is the cause - gotcha. compiler is likely optimising it.. yep! as for the sizeof(*new vector/array) - it was simply a dumb demonstration - if the vector object contained the buffer of 10x long ints its size would exceed 80 bytes - it does not and clearly the vector object stores a reference/pointer to its buffer. i was aware but trying to demonstrate the point - i am fully aware it is incorrect – Adam W Oct 29 '17 at 14:23