0
#include<stdlib.h>
typedef struct
{
    int *member;
} mystruct;

void main(int argc, char *argv)
{
    mystruct **data;
    data = (mystruct**)malloc(sizeof(mystruct*));
    int c = 5;
    printf("%x", data);
    (*data)->member = &c;
    printf("Member: %d", *((*data)->member));
}

Error: Segmentation fault

I expected it would print "5" in the source code

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 1
    Okay, you allocate a pointer to a mystruct. Which mystruct does that pointer point to? – user253751 Feb 16 '23 at 15:03
  • Sidenote: [don't cast malloc.](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – B Remmelzwaal Feb 16 '23 at 15:04
  • `(*data)` good, dereferencing the pointer returned by `malloc`. `->member` ***bad***, dereferencing uninitialized memory (inside the chunk returned by malloc), not a valid pointer. – Marco Bonelli Feb 16 '23 at 15:11
  • Take a pencil and a piece of paper and draw the pointer with arrows where they point to, and it should become pretty clear why your program doesn't work as expected. – Jabberwocky Feb 16 '23 at 15:37

2 Answers2

1

Error: Segmentation fault

I expected it would print "5" in the source code

It is because you have only allocated a pointer to your struct and this pointer is not referencing a valid memory location. It invokes Undefined Behaviour (UB). You need to allocate the space for the structure itself.

int main(int argc, char *argv)
{
    mystruct **data;
    data = malloc(sizeof(*data));
    *data = malloc(sizeof(**data));
    int c = 5;
    printf("%p %p", (void *)data, (void *)*data);
    (*data)->member = &c;
    printf("Member: %d", *((*data)->member));  //or*data[0]->member))
}
  • void main(.... is invalid
  • do not cast the result of malloc. If it does not compile - you use C++ compiler to compile C code which is wrong
  • use objects instead of types in sizeof
  • you have to use %p format to print pointers. Pointers have to be converted to void *
0___________
  • 60,014
  • 4
  • 34
  • 74
0

In this statement

data = (mystruct**)malloc(sizeof(mystruct*));

you allocated memory for one pointer of the type mystruct *. That is uninitialized.

Thus dereferencing this uninitialized pointer obtained by the expression *data

(*data)->member = &c

invokes undefined behavior.

At least you should write

data = (mystruct**)malloc(sizeof(mystruct*));
*data = malloc( sizeof( mystruct ) );

That is you need to allocate memory for an object of the type mystruct the data member member of which will be assigned.

Also pay attention to that using the conversion specifier %x to output a pointer

printf("%x", data);

also invokes undefined behavior. Instead you need to write

printf("%p\n", ( void * )data);

Or you could include header <inttypes.h> and write

#include <inttypes.h>

//...

printf("%" PRIxPTR "\n", ( uintptr_t )data);
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • thanks that is really helpful. Still, I want to ask why we have to cast (void *) – hoang15nguyen Feb 16 '23 at 15:41
  • @hoang15nguyen It is a requirement for the conversion specifier p. From the C Standard "p The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner." – Vlad from Moscow Feb 16 '23 at 15:50