0

My question is regarding a problem I encountered recently on my code. Long story short, there was a function getting a dynamicly allocated array of hashtables as following void output(Hashtable* hash_array). Inside the function was the following piece of code int k=some_function(); int results[k];

The problem was: After running the program for a while, data inside hash_array were lost. In an attempt to debug the program, I tried printing the value of hash_array with fprintf(stderr,"%p\n",hash_array); and it turns out that hash_array had value (nil) just before the segmentation fault, even though function output was only reading data from hash_array. The problem was fixed when I changed int results[k]; into int* results=new int[k];

So I have two questions regarding this:

  1. What exactly does the compiler do when it encounters a static array declared with a variable size like in int results[k];?
  2. How did (or could) int results[k]; affect the hashtable array?
Emroy
  • 85
  • 10
  • 3
    Code says more than a thousand words. Please try to create a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve) and show us instead. – Some programmer dude Jan 07 '16 at 08:31
  • 2
    Also note that [variable-length arrays](http://en.wikipedia.org/wiki/Variable-length_array) are not a standard C++ feature. If you want a variable-length array use [`std::vector`](http://en.cppreference.com/w/cpp/container/vector). – Some programmer dude Jan 07 '16 at 08:32
  • As for your problem, you might go out of bounds of the array, leading to *undefined behavior*. Use a debugger to catch any crash in action, and check the call-stack as well as the values of all involved variables. *Or* you try to return the `results` array, which you can't since it's a local variable and local variables go out of scope once the function returns, also leading to *undefined behavior*. – Some programmer dude Jan 07 '16 at 08:34
  • This is not static array but automatic array in the stack. My recommendation is not to use such "trick". Allocate with `malloc` and avoid exotic bugs. – i486 Jan 07 '16 at 08:37
  • 1
    Make your function return a `std::vector` instead of using C-style arrays. Prefer `size_t` or `unsigned int` instead of `int`: it makes not sense to have a negative size, so a signed type is not the appropriated one. Note that `new` may throw a `std::bad_alloc` if the allocation fails. – vincentp Jan 07 '16 at 09:13
  • I am not trying to fix my code here, the code has already been fixed. That's why I am not giving actual coding and just explaining what happened. What I am intrested in is learning what actualy happened there, because even though I fixed it I still don't understand what exactly was the problem. I don't think that reproducing the problem will help people explain what kind of code the compiler produces when `type identifier[identifier];` is encountered, but if you think it will I can try to reproduce it. – Emroy Jan 07 '16 at 09:52
  • `I don't think that reproducing the problem will help people explain what kind of code the compiler produces` No, but it allows us to tell you what was wrong with the code and why. – eerorika Jan 07 '16 at 09:59

2 Answers2

1
  1. What exactly does the compiler do when it encounters a static array declared with a variable size like in int results[k];?

To be pedantic, according to your description, the array appears to be automatic, rather than static. Variable length arrays can not even be static.

According to C++11, the compiler should issue a diagnostic, because variable length (non-dynamic) arrays are not allowed by the standard and the program is therefore ill formed as far as the standard is concerned.

A compiler might support variable length arrays as an extension to the language. The support is quite common because variable length arrays are allowed in C. It can be implemented differently in different compilers. Here's a SO question about gcc's implementation.

Here is a description of what the compiler does in high enough level to be non-implementation specific: When the definition of the array is reached, memory is allocated for the array. When the variable goes out of scope, the memory is deallocated.

  1. How did (or could) int results[k]; affect the hashtable array?

Just the allocation and initialization has no effect on other arrays. How it's used, can have. Especially if you have undefined behaviour.

Community
  • 1
  • 1
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • One more thing. This memory is allocated on heap, static or stack? Or does this also depend on the implementation? – Emroy Jan 07 '16 at 10:19
  • @Emroy Very unlikely to be static, since the size of static memory cannot change while the program runs - might be used in an embedded environment (though, I find it unlikely that VLA would be supported at all in embedded environment). Stack is typical, and that's where gcc allocates. Heap is possible. – eerorika Jan 07 '16 at 10:39
0

Code like this:

int k = some_function();
int results[k];

Causes the necessary space for results to be allocated on the stack... and then, like any local variable, that memory is given up after the function returns.

When you switched to doing:

int* results=new int[k];

You're now allocating memory on the heap (which doesn't automatically go away).. thus your hash table is still accessible, but you're now leaking memory.

Buddy
  • 10,874
  • 5
  • 41
  • 58
  • His first question is "What exactly does the compiler do", Buddy. Check the assembly and update your answer appropriately. –  Jan 07 '16 at 08:49
  • I understand about stack and heap allocation, but that doesn't explain what could have happened to hash_array, nor does it explain what kind of code the compiler produces when a static array is declared with a variable instead of a literal giving the size. – Emroy Jan 07 '16 at 09:45