A word of warning about extern: pointers and arrays
Posted: Wed Jul 03, 2013 1:47 pm
Simply put I was working with someone elses code (don't really know who's) and found a super nasty bug where the processor would take off into a random memory space and die. The problem is, everything looked good and correct in the source, so why was it blowing up? To understand, answer for yourself the question, what's the difference in meaning (both allocation and use) of the following:
If we ignore the possibility of a malloc failure, then there is effectively no difference and anything you can do with one, you can do in exactly the same way with the other.
Now, let's consider the following (in a different source file, of course):
Is anything different? Can they still be used the same way? If you said yes, sorry, you're going to be reading garbage, and if it's a list of functions, you're now in random memory land...
So, if they're different, how are they different? why are they different?
To understand what's going on, you have to understand what extern is telling the compiler. extern says to the compiler that it won't find the token declared or allocated anywhere in the current source file, but that where it is defined, it's the given type. This is why when you use externs but forget to declare the variable somewhere else the linker fails with 'undefined reference'; this is an interesting point, because it doesn't say 'unallocated variable'. The reason for 'undefined reference', is that declaring something extern causes the linker to look for a 'reference' or 'symbol' to a memory location containing the data.
In the event where we declare an extern pointer, we're telling the linker that at the location of the symbol exists data that is a pointer to something else. However, when we declare an extern array instead, the linker knows that the symbol is actually an array starting where it found the symbol. Therefore, when we use the [] operator to get at an individual element, the data at the pointer symbol's location will be dereferenced to find the array, but the data at the array symbol's location is treated as the array itself.
Hope this serves as an education to folks, because of the dozen or so C/C++ devs I asked about this this week, none of them knew the difference. Did any of you know?
-Dan
[Edit: added length to local array declaration per ecasey's comment below.]
Code: Select all
type * foo = malloc(n*sizeof(type));
type foo[n];
Now, let's consider the following (in a different source file, of course):
Code: Select all
extern type * foo;
extern type foo[];
So, if they're different, how are they different? why are they different?
To understand what's going on, you have to understand what extern is telling the compiler. extern says to the compiler that it won't find the token declared or allocated anywhere in the current source file, but that where it is defined, it's the given type. This is why when you use externs but forget to declare the variable somewhere else the linker fails with 'undefined reference'; this is an interesting point, because it doesn't say 'unallocated variable'. The reason for 'undefined reference', is that declaring something extern causes the linker to look for a 'reference' or 'symbol' to a memory location containing the data.
In the event where we declare an extern pointer, we're telling the linker that at the location of the symbol exists data that is a pointer to something else. However, when we declare an extern array instead, the linker knows that the symbol is actually an array starting where it found the symbol. Therefore, when we use the [] operator to get at an individual element, the data at the pointer symbol's location will be dereferenced to find the array, but the data at the array symbol's location is treated as the array itself.
Hope this serves as an education to folks, because of the dozen or so C/C++ devs I asked about this this week, none of them knew the difference. Did any of you know?
-Dan
[Edit: added length to local array declaration per ecasey's comment below.]