SatView: Pointer Perfect, part 4 - Fence Post Errors
(Page 2 of 5 )
When you construct an array of objects in memory, there is always the possibility that you might accidentally try to access or set an object outside the bounds of this array. C/C++ arrays can be confusing to index when you are not used to thinking of the first object as having index 0. The ‘off by one’ error is easily made:
char arry[10]; // declare array of chars
arry[10]=1; // mistake! This is the 11th element of arry!
This is the reason why loops iterate from 0 to size-1:
for (int idx=0; idx<10; ++idx) { /* do operation */ }
Errors like these can be very subtle, however, and since we are dealing with pointers, let's see how a fence post error can create a wild pointer:
struct Fence {
int arry[10];
int *pInt;
};
void test() {
Fence fence;
memset(&fence, 0, sizeof(Fence)); // initializing all fence vars to 0!
fence.pInt = new int(2);
fence.arry[10] = 1;
(void)printf(“fence.pInt = %d.\n”, *fence.pInt);
delete fence.pInt;
}
If you compile and run the code above, Win32 will come up with the following complaint:
The instructions at “0x00414137” referenced memory at “0x00000001”. The memory could not be “read”.
How is it possible that fence.pInt, which was properly initialized with new int(2), suddenly points at address 0x00000001? To understand this you must look at the way the compiler constructs the memory layout for Fence:
0x0012FDA0 00000000 .... <- fence.arry[0]
0x0012FDA4 00000000 .... <- fence.arry[1]
0x0012FDA8 00000000 .... <- fence.arry[2]
0x0012FDAC 00000000 .... <- fence.arry[3]
0x0012FDB0 00000000 .... <- fence.arry[4]
0x0012FDB4 00000000 .... <- fence.arry[5]
0x0012FDB8 00000000 .... <- fence.arry[6]
0x0012FDBC 00000000 .... <- fence.arry[7]
0x0012FDC0 00000000 .... <- fence.arry[8]
0x0012FDC4 00000000 .... <- fence.arry[9]
0x0012FDC8 002f11b0 °./. <- fence.pInt pointing at 0x002F11B0
The address of arry is 0x0012FDA0 and arry+10*sizeof(int) (arry[10]) equals 0x12FDC8… the address of fence.pInt! So by setting arry[10] to 1, we are effectively changing the pointer fence.pInt and are therefore crashing when we try to reference it.
Next: Dangling Pointers >>
More C# Articles
More By J. Nakamura