6

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)?

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
user2081740
  • 81
  • 1
  • 3
  • 9
  • 1
    Your code behavior is Undefined means at different execution you may notice different behavior, you can't predict in advance, your program may be crash sometime. This code is wrong! unreliable unfortunately C compiler doesn't report this. – Grijesh Chauhan Jul 09 '13 at 03:09

6 Answers6

9

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".


* Arguably, the worst.
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
3

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.

Travis DePrato
  • 392
  • 3
  • 9
3

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.

Community
  • 1
  • 1
Nobilis
  • 7,310
  • 1
  • 33
  • 67
1

C doesn't do bounds checking. You are stomping on memory that your program doesn't own.

1

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

Sabashan Ragavan
  • 728
  • 1
  • 5
  • 14
1

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.

Jacob Pollack
  • 3,703
  • 1
  • 17
  • 39