Reputation: 91
I am trying to create an array of size 2, dynamically, using malloc. Here is my code:
int *d = (int*)malloc(2 * sizeof(int));
d[0] = 4;
d[1] = 5;
d[2] = 8;
d[3] = 9;
d[4] = 7;
int i;
for (i = 0; i < 5; i++)
printf("%d \n", d[i]);
When I run this code, it prints 4, 5, 8, 9, 7
.
I am wondering how it was able to allocate more memory (5 integers) than I requested (2 integers)?
Upvotes: 6
Views: 10107
Reputation: 3751
The reason this appears to work is because you are incrementing your pointer to point to new spots in memory (which your program may or may not be allocated to use). I am guessing you are declaring this on the stack and that is why your undefined behavior appears to be "ok".
I do not think you understand the power of a pointer and the syntax you used. Remark that the following is equivalent:
int arr[ 2 ] = { 1, 2 };
int *pi = &arr;
// The following output is equivalent to...
for ( int i = 0; i < 2; i++ ) {
printf( "arr[i] = %d.\n", arr[ i ] );
}
// this.
for ( int i = 0; i < 2; i++ ) {
printf( "*(p + i) = %d.\n", *( p + i ) );
}
Consider this, alternate implementation of your code to emphasize how you are pointing to new memory addresses by indexing elements outside of your array.
int *d = ( int * )malloc( 2 * sizeof( int ) );
*( d + 0 ) = 4; // Observe you are accessing the memory location d points to.
*( d + 1 ) = 5; // Observe you are accessing the memory location d + 4 bytes (or 8 if 64-bit) points to...
*( d + 2 ) = 8; // ...
*( d + 3 ) = 9; // ...
*( d + 4 ) = 7; // Observe you are assigning a value to the memory location of d + 24 bytes (or 48 bytes if 64-bit).
for ( int i = 0; i < 5; i++) {
printf( "%d \n", *( d + i ) );
}
Just a quick note on your code. A malloc should typically be followed by a free -- so use it appropriately so there are no memory leaks.
I hope this helped! Feel free to correct me if I made a mistake.
Upvotes: 1
Reputation: 7448
In addition to what's been suggested if I could add a few extra notes.
Not sure what OS you are running this on but if you are on Linux any time you're unsure if something should work or not run it through valgrind
. In my case it compiled a nice report about all the errors with your code (including not freeing the malloc
-ed memory).
I got three Invalid write of size 4
for the three extra writes you do to the memory. It also notified me of the invalid memory that you are reading in the loop with Invalid read of size 4
and finally it gave me some stats on the leaks in your code:
HEAP SUMMARY:
in use at exit: 8 bytes in 1 blocks
total heap usage: 1 allocs, 0 frees, 8 bytes allocated
LEAK SUMMARY:
definitely lost: 8 bytes in 1 blocks
Finally, don't cast the result of malloc.
Upvotes: 3
Reputation: 738
When you are invoking undefined behavior, you never know what might happen. For example when I ran the program I got the following as my output:
4, 5, 8, 51, 1629501832
Upvotes: 1
Reputation: 61
C doesn't do bounds checking. You are stomping on memory that your program doesn't own.
Upvotes: 1
Reputation: 402
Like Oli said, it's undefined. It may work, it may not. But the reality is that even though it might work 99% of the time, it will, at least once, fail, and you'll get a SEGFAULT
from reading or writing memory that your process isn't supposed to be using, and you'll also end up with virtually un-debugable memory leaks.
Upvotes: 3
Reputation: 272467
i wondering how it was able to allocate more memory than I requested.
It didn't. You are invoking undefined behaviour. One possible outcome* is that your program appears to "work".
Upvotes: 9