简体   繁体   中英

why does malloc(sizeof(pointer)) work?

This following code works fine:

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

int main()
{
    struct node{
        int a, b, c, d, e;
    };
    struct node *ptr = NULL;
    printf("Size of pointer ptr is %lu bytes\n",sizeof (ptr));
    printf("Size of struct node is %lu bytes\n",sizeof (struct node));
    ptr = (struct node*)malloc(sizeof (ptr));               //Line 1
//    ptr = (struct node*)malloc(sizeof (struct node));    //Line 2

    ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5;
    printf("a: %d, b: %d, c: %d, d: %d, e: %d\n",
            ptr->a,ptr->b,ptr->c,ptr->d,ptr->e);
    return 0;
}

When complied as:

gcc -Wall file.c

My question is: why is this fine?

malloc allocates the number of bytes which are specified in it's argument. Here sizeof ptr is 8 bytes on my 64-bit linux machine. I thought malloc will provide 8 bytes but then how is it accessing all the variables a,b,c,d,e? Is it with gcc only or am I missing something with standard C?

As far as I know "Line 2" should be there instead of "Line 1" but either of the line works fine. Why?

You have undefined behavior here.

malloc will allocate 8 bytes (as you say), but this cast is "bad":

ptr = (struct node*)malloc(sizeof (ptr));

After this line, ptr will point to a memory block, which has only 8 allocated bytes, the rest are some "random" bytes. So, making

ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5;

you actually change some memory, not only the allocated by malloc .

In other words, you are rewriting memory, you're not supposed to touch.

Line 1 is incorrect and won't allocate sufficient space. If you can access the structure members later it is only because C does nothing to prevent you from accessing memory that doesn't belong to you.

Accessing ptr->b , ptr-c , etc., when you haven't allocated enough space for the entire structure is undefined behavior, and the next time that you run your code it could crash, or you could end up overwriting data in another part of your program.

To demonstrate the problem, allocate a second struct node immediately after the first. This isn't guaranteed to demonstrate the problem, but you're likely to see results similar to the following:

struct node *ptr = NULL;
struct node *ptr2 = NULL;

ptr = (struct node*)malloc(sizeof (ptr));  // Your Line 1
ptr2 = malloc(sizeof(struct node));        // alloc another struct on the heap

ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5;
ptr2->a = 11; ptr->b = 12; ptr->c = 13; ptr->d = 14; ptr->e = 15;

printf("ptr:  a: %d, b: %d, c: %d, d: %d, e: %d\n",
        ptr->a, ptr->b, ptr->c, ptr->d, ptr->e);
printf("ptr2: a: %d, b: %d, c: %d, d: %d, e: %d\n",
        ptr2->a, ptr2->b, ptr2->c, ptr2->d, ptr2->e);

Output:

ptr:  a: 1, b: 2, c: 3, d: 4, e: 11
ptr2: a: 11, b: 12, c: 13, d: 14, e: 15

Note that ptr->e has been modified by the assignment to ptr2->a , so you can see that one improperly-allocated structure is stepping on the memory of another. This certainly isn't what you want.

malloc is allocating only 8 bytes, but that doesn't stop you accessing memory beyond that. You will probably corrupt the heap and might write over other objects. The behaviour of the program is undefined.

In ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5; ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5; you are accessing beyond the memory allocated by the malloc.
This is a case of buffer overflow and causes undefined behaviour .

It is possible because

 C and C++ provide no built-in protection against accessing or overwriting data
in any part of memory.

so, it may work sometime, sometime it may crash the program also.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM