user2081740
user2081740

Reputation: 91

Dynamic memory allocation of integer array

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

Answers (6)

Jacob Pollack
Jacob Pollack

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

Nobilis
Nobilis

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

Sabashan Ragavan
Sabashan Ragavan

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

Craig Neil Brown
Craig Neil Brown

Reputation: 61

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

Upvotes: 1

Travis DePrato
Travis DePrato

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

Oliver Charlesworth
Oliver Charlesworth

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


* Arguably, the worst.

Upvotes: 9

Related Questions