1

We went over differing compiler behavior today in my data structures class. The example below (plus some of my cout'ing and other tinkering) was given as a program that could compile on g++ but not necessarily on all other compilers.

#include <iostream>

using namespace std;

int main(void)
{
    int i;
    int j = 5;

    cout << "i address: " << &i << " -- j address: " << &j 
         << endl << "enter size: ";
    cin >> i;
    cout << "value i: "<< i << "; size memory of i (ints): "<<(&i - &j)<< endl;

    int a[i];

    cout << "address of array a start: " << a << endl;

    int b = 14;

    cout << "value b: " << b << "; b address= " << &b << endl
         << "distance bt j and b(ints): "<< (&j - &b) << endl;
    cout << "distance bt b and start of array(ints): " << (&b - a) << endl;
}

After playing around with inputs (and learning a little about how dynamic arrays are allocated memory in the process), I decided that entering 0 was the most interesting. The output:

i address: 0x7fff5b303764 -- j address: 0x7fff5b303760
enter size: 0
value i: 0; size memory of i (ints): 1
address of array a start: 0x7fff5b3036b0
value b: 14; b address= 0x7fff5b303754
distance bt j and b(ints): 3
distance bt b and start of array(ints): 41

My Questions:

  1. How does g++ know to treat the array a as one which needs to be dynamically created vs immediately trying to statically create one with whatever the default value of i is or throwing some sort of compile time error?

  2. The distance between j and b is 3 ints worth of memory instead of the expected 1. What is going on with that? I suspect, purely from empirical evidence gathered by playing around with the program, that it has something to do with the couts, but I'm unfamiliar with how/why they would be stored in memory in seemingly random amounts.

  3. I entered 0 for size of array a and, based on playing around with different sizes, I think it is unlikely that a dynamic array of length 0 would be initialized to length 41. So, if it is not the array taking up all of those 41 ints worth of memory, what then is stored between b (the last data stored on the stack) and the array a (the first data purposefully stored on the heap) and why is whatever it is there?

3
  • All of these pointer subtractions cause undefined behaviour. It might be instructive to examine the assembly code produced by this program, in order to understand what g++ is doing. Commented Oct 8, 2014 at 3:41
  • Link to unoptimized assembly Commented Oct 8, 2014 at 3:49
  • @MattMcNabb I have never worked with assembly language before. But it's great to know that I can use it as a resource to more deeply examine exactly what is going on in these situations in the future. Will definitely take a look back at the link you provided when I feel comfortable enough with the topic to do so as there are still some ambiguities as to just what exactly is going on here. I appreciate your time and effort in responding to my questions. Cheers. Commented Oct 8, 2014 at 4:15

1 Answer 1

2

a is a variable-length array which is not part of standard C++ but a g++ extension. g++ knows that it is not a regular array with size determined at compile-time, because i is not a compile-time constant, such as const int i = 3; a is not stored on the heap. It is stored on the stack. I imagine the address distance between j and b depends on the size allocated to a, which can only be known at run-time. I don't know how to account for the distance between b and a for size 0. If you built in debug-mode, it's possible that some extra hidden buffer was added after the array in order to detect an accidental overwrite beyond the bounds of the array.

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

10 Comments

According to what you said, the memory allocated to a is on the stack and also allocated at runtime? How is it not in between j and b in this case? Their relative positions in memory go like this (distances in ints) i -1-> j -3-> b -41-> a. How can the distance between j and b be accounted for by a if a is after b not in between them? Does it get moved at some point?
@jvanstry I did not look too closely at the precise numbers. The compiler is able to reorder these variables on the stack if it wants to. Also sometimes for x - y, you put the variable later first and sometimes the variable earlier first. I don't know how that will affect the calculation.
The compiler can arrange variables on the stack however it wants. Most likely, it puts all the variable-length stuff above all the fixed-size stuff so that all the fixed-size variables are at constant positions that don't depend on the size of the array.
@Wyzard when you say above, do you mean at a lower # memory address?
It seems like I'm getting contradictory answers here: @Wyzard stated the dynamic elements are stored above the static ones, and Neil Kirk mentioned that the 3 int spacing bt j and b is based on a, implying its between these elements. Could someone clear up this apparent discrepancy?
|

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.