Initializing struct from struct** - segfault

1772 views c
-1

I'm trying to initialize a struct, from a pointer, to a pointer. I'm doing this with an init function. This, however gives a segfault. The pointer i'm trying to initialize from, is defined within an array. When the size of the array is set to 1, the segfault does not occur.

typedef struct{
  int a;
}myStruct;

void init_struct(myStruct** s){
  (*s)->a=10;
}

void fun(myStruct** sp){
  init_struct(sp);
}

int main(){
  myStruct* s[2];
  fun(&s[0]);
}

I know this is because I'm accessing memory I'm not supposed to, but why am i not allowed in this case? Why is this ok when the size of the array is 1? (I'm assuming undefined behavior)

This is a simplified part of a school assignment, so i'm not allowed to alter the contents of 'main'.

answered question

what's fun supposed to do?

3 Answers

7

With myStruct* s[2], you reserve memory for two pointers to myStruct, but you do not initialize these pointers in order to let them point to valid myStruct-objects. Dereferencing such an (uninitialized) pointer then yields undefined behaviour (very likely a segfault).

A command like

s[0] = malloc(sizeof(myStruct));

should solve this at least for the first pointer.

posted this
3

the posted code fails to actually allocate any memory for the actual struct instance.

So trying to write where the pointer points is writing to memory that the application does not own

posted this
8

Note that myStruct * s[2] simply declares an array of 2 unititialized pointers (to structs of the myStruct type).

The pointers may very well point to invalid memory, which you are accessing in init_struct by the following expression: (*s)->a (which, in case you didn't already know, is equivalent to s[0]->).

You could fix the invalid memory access, by allocating the memory required to fit the structure:

s[0] = malloc(sizeof s[0]);

You should also check if malloc succeeded allocating the memory:

if (s[0] == NULL) {
    return; // error
}

Then you may freely write to the uninitialized members of the myStruct you just allocated:

s[0]->a = 10;

Note that your application will have a memory leak, unless you also free the allocated memory:

free(s[0]);

Furthermore, you may check for errors using the very useful tool valgrind which should give you the following output:

$ valgrind ./a.out
==12820== Memcheck, a memory error detector
==12820== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==12820== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==12820== Command: ./a.out
==12820== 
==12820== 
==12820== HEAP SUMMARY:
==12820==     in use at exit: 0 bytes in 0 blocks
==12820==   total heap usage: 1 allocs, 1 frees, 8 bytes allocated
==12820== 
==12820== All heap blocks were freed -- no leaks are possible
==12820== 
==12820== For counts of detected and suppressed errors, rerun with: -v
==12820== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

posted this

Have an answer?

JD

Please login first before posting an answer.