5

So I do have to write a vector-like data structure in C. Generally I made a structure like this:

struct Vector { int length; int *elements; }; 

And functions like these:

void initialize_vector(struct Vector* vector); void create_vector(struct Vector* vector, int* array, int n); void remove_vector(struct Vector* vector); void vector_add_element(struct Vector* vector, int element); void vector_insert(struct Vector* vector, int index, int element); void vector_remove_element(struct Vector* vector, int element); void vector_remove_at(struct Vector* vector, int index); 

Now, the initialize_vector() function, I wanted it just to initialize vectors attributes to default values (like length to 0 and *elements to NULL). I wrote something like this:

void initialize_vector(struct Vector* vector) { vector->elements = NULL; vector->length = 0; } 

And I tried to check if it works, so I wrote this piece of code:

#include <stdio.h> #include "vector.h" int main(int arc, char** argv) { struct Vector* vec; initialize_vector(vec); printf("%d\n", vec->length); return 0; } 

I got famous Segmentation fault, so I checked on GDB, and of course the moment when everything screws up is this line: vector->elements = NULL;.

I don't know where the problem is. I declare a vector, I pass it properly I guess and it messes up. I know that is probably trivial and I will get massively downvoted by some uberprogrammieren guys, but hey, he that nothing questioneth nothing learneth.

3
  • 1
    1: Change struct Vector* vec; to struct Vector vec; initialize_vector(vec); to initialize_vector(&vec); to pass the function a pointer to the structure. 2: Create an instance to a Vector with malloc(). Commented Jun 15, 2017 at 18:52
  • There is no memory allocated for the struct. Commented Jun 15, 2017 at 18:52
  • " I declare a vector" - No! You declare and define a pointer to struct Vector. A pointer is not the same as the type it points to! Details are essential in programming! "the moment when everything screws up is this line …" - You screwed up much earlier! Compiler warnings are not for fun! Enable them and pay heed! Commented Jun 15, 2017 at 18:55

2 Answers 2

13

You didn't declare a vector, you declared a pointer to a vector. That pointer is uninitialized, so attempting to dereference it invokes undefined behavior.

Create a struct Vector and pass its address:

struct Vector vec; initialize_vector(&vec); printf("%d\n", vec.length); 

If you want to allocate space for a struct Vector at the same time, change the function to call malloc and return the pointer:

struct Vector *initialize_vector() { struct Vector *vector = malloc(sizeof(*vector)); if (!vector) { perror("malloc failed"); exit(1); } vector->elements = NULL; vector->length = 0; return vector; } ... struct Vector *vector = initialize_vector(); 
Sign up to request clarification or add additional context in comments.

4 Comments

I've deleted my answer. Thanks for helping me understand. Why is the reference to the memory lost?
Yes, exactly. Works perfectly, thank you. And by the way, whats the better way to store it, create a vector, create pointer to a vector and operate on its pointer, or just keep it as a normal vector and just always pass it by address? Or as @Coldspeed suggested, use mallloc() to actuall make it exist
@Coldspeed You're modifying a local variable. That modification is not visible outside of the function.
@FrynioS You can have the initialization function allocate and return a pointer. See my edit.
1

dbush gave a great answer so I won't give you code. Instead, I'll give a little C pointer explanation so you don't run into the same error again.

struct Vector* vec;

declares a pointer to a struct, not an actual struct. What is a pointer exactly? It is a variable that holds an address. Consequently, all pointers, no matter if they are an int *, char *, char **, or struct Vector *, have the same size (usually 32 or 64 bits depending on architecture). Declaring the type of pointer is only useful for dereferencing the pointer (getting the data that is stored in that memory address). It makes sense then that dereferencing a void * pointer leads to an error. Returning to the above statement, in English, this declaration reads: "vec is a variable that can hold the address of a struct Vector." At this moment however, vec does not hold a valid address.

Until you assign a pointer variable a value, the address stored in that variable is garbage, we call this an uninitialized variable. In your case, you then passed this uninitialized address to initialize_vector(), which attempted to access the value stored in that address. But as we know, that address is garbage. This gave the seg fault.

Another thing to point out is that when writing functions such as these, you have a design decision to make. Do you want the struct Vectors to live on the heap (by calling malloc) or on the stack? The heap allows for more flexibility but it also requires the programmer to keep careful track of the pointers that are in use in order to avoid memory leaks, and this can get tricky. If I were you I would start out with objects that live on the stack and then pass their address to the modifying functions. dbush's first answer. This way you don't have to worry about calling free().

1 Comment

Yeah, but then I need to have malloc()s, cuz the lab guy told us, that our structures have to be allocated dynamically :D