0

I know I should be using realloc to grow an array but in a momentary lapse of thought I did it this way. I realize the approach is wrong as I am corrupting the heap by growing it without allocating the array. So I am essentially writing garbage. But when the code is small and nothing else is happening I don't see why this should not work. I get garbage for the first few values

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int **p = NULL;
    int i=0;
    int size = 5;
    int *n = NULL;

    p = malloc(sizeof(int*));

    printf("p = %p \n", p);

    for( i=0; i < size; i++ )
    {
        int *k;
        k = malloc(sizeof(int));
        *k = i;
        p[i] = k;
        printf("%p, %p, val = %d \n", k, p[i], *k);
    }

    printf("Now print the array -- \n");
    for( i=0; i < size; i++ )
    {
        int *k;
        k = p[i];
        printf("value at mem %p == %d \n", p[i], *k);
    }

    printf("now print the next values in p \n");
    for( i=0; i < size; i++ )
    {
        printf("value at %p = %p \n", p+i, *(p+i) );
    }

    return 0;
}

Here is the output of the code --

p = 0x7f8ffbc031c0
0x7f8ffbc031d0, 0x7f8ffbc031d0, val = 0
0x7f8ffbc031e0, 0x7f8ffbc031e0, val = 1
0x7f8ffbc031f0, 0x7f8ffbc031f0, val = 2
0x7f8ffbc03200, 0x7f8ffbc03200, val = 3
0x7f8ffbc03210, 0x7f8ffbc03210, val = 4
Now print the array --
value at mem 0x7f8ffbc031d0 == -71290384
value at mem 0x7f8ffbc031e0 == -71290352
value at mem 0x7f8ffbc031f0 == 2
value at mem 0x7f8ffbc03200 == 3
value at mem 0x7f8ffbc03210 == 4
now print the next values in p
value at 0x7f8ffbc031c0 = 0x7f8ffbc031d0
value at 0x7f8ffbc031c8 = 0x7f8ffbc031e0
value at 0x7f8ffbc031d0 = 0x7f8ffbc031f0
value at 0x7f8ffbc031d8 = 0x7f8ffbc03200
value at 0x7f8ffbc031e0 = 0x7f8ffbc03210

I cannot explain why the first two values are garbage even though the memory address pointed to by p and p+1 are what I put there.

9
  • Probably because you corrupted the heap. Commented Jul 19, 2017 at 22:59
  • 1
    Or more specifically: You'll notice that p[2] and *p[0] have the same address - the third pointer overwrote the first number. Same for p[4] and *p[1]. Commented Jul 19, 2017 at 23:01
  • 2
    p = malloc(sizeof(int*)); only allocates memory for one int* but the later p[i] = k; breaks it. Commented Jul 19, 2017 at 23:01
  • 3
    You say you know you should be using realloc to grow an array but in a momentary lapse of thought you did it this way. You realize the approach is wrong but still want to know why you are writing garbage. Hmm.... answer: write it properly :) Commented Jul 19, 2017 at 23:04
  • @immibis -- thanks I did not notice that. I know its wrong. Just couldnt see what exactly is going wrong. I should have seen that malloc will give me the next available pointer and should have seen that p[2] would be wrong. Commented Jul 19, 2017 at 23:06

3 Answers 3

1

The statement

p = malloc(sizeof(int*));

only allocates a single element to p; p[1] through p[4] don't exist (or, more properly, you don't own the memory corresponding to those elements). To allocate a size-element array of int *, that line needs to be

p = malloc( size * sizeof *p ); // sizeof *p == sizeof (int *)

Also,

int *k;
k = malloc(sizeof(int));
*k = i;
p[i] = k;

could simply be written as

p[i] = malloc( sizeof *p[i] ); // sizeof *p[i] == sizeof (int)
if ( p[i] ) // **always** check the result of a malloc, calloc, or realloc call!
  *p[i] = i;
Sign up to request clarification or add additional context in comments.

Comments

0

The program has undefined behavior. Nevertheless I can explain the result of this program run.

Usually when a memory allocation request is less than the size of the paragraph that is usually equal to 16 bytes then the function malloc allocates a chunk of memory exactly equal to the size of paragraph.

So after this statement

p = malloc(sizeof(int*));

there was allocated 16 bytes at address

p = 0x7f8ffbc031c0

Thus you can use addresses

0x7f8ffbc031c0 and 0x7f8ffbc031c8 that belong to the allocated extent.

The first and the second chunks allocated in the loop by the statement

k = malloc(sizeof(int));

is

0x7f8ffbc031d0
0x7f8ffbc031e0

In the same loop due to the statement

    p[i] = k;

there are accesses the memory beyond the allocated extent pointed to by the pointer p.

so you have for the expression p[i] sequentially

0x7f8ffbc031c0   - p[0] 
0x7f8ffbc031c8   - p[1]
0x7f8ffbc031d0   - p[2]  - Oops! the address 0x7f8ffbc031d0 is overwritten
0x7f8ffbc031d8   - p[3]  
0x7f8ffbc031e0   - p[4]  - Oops! the address 0x7f8ffbc031e0 is overwritten!

So the first two addresses where the first two integers were stored are overwritten.

Comments

0

Your code is wrong. You declare p as single pointer to pointer, but then you use it as an array of size items. To do that you must allocate the array of required size. Your current p = malloc(sizeof(int*)) allocates just a single pointer, correct code would be p = (int**)malloc(size * sizeof(int*)).

I tested your code in Visual Studio and I can't see any garbage in p[0] and p[1]. I assume it is based on how your compiler and/or operating system organizes heap. Since you didn't specify them in your question, it is hard to comment.

So you don't allocate memory for p[1] to p[4]. But you write values to there. So where do you think those values actually go? Those values are written to RAM, but it is not a memory you own for p[] array. Those two strange numbers -71290384 and -71290352 are actually values you wrote to p[2] and p[4]. (It is ff8ffbc031f0 hex and ff8ffbc03210 hex respectively, upper bit is set but that is irrelevant.) It is because when you write to p[2], you actually write to memory allocated for that other local k. This behavior depends on concrete heap organization, so it differs on other operating systems and/or compilers.

Also, while p[2] and p[4] are accidentally written to memory allocated for other variables, it seems that by writing to unallocated p[1] and p[3] you corrupted your heap.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.