3

I've done alot of looking around, but still can't get my head around it, lets say I have struct:

struct some_struct {
    int x;
    int y;
    char *some_string;
};

Lets say we have the above struct, how would you allocate some memory for the above struct? One can simply do:

struct some_struct *test_struct;
test_struct = malloc(sizeof(struct some_struct));

But is this enough? Don't you need to allocate some memory for some_string? Or if the struct contains more pointers, do you not need to allocate memory for them as well?

Edit: One more thing... assuming my struct some_struct already has data in it e.g.

struct some_struct *test_struct = malloc(sizeof(some_string);
test_struct->x = 2;
test_struct->y = 3;
test_struct->some_string = "sadlfkajsdflk";

Will the following code suffice in freeing allocated memory?

free(test_struct);

or do I have to go in and free the char* some_string as well?

Thanks

chutsu
  • 13,612
  • 19
  • 65
  • 86
  • 1
    Regarding the edit, you let `test_struct->some_string` point to a string literal, not to memory `(m|c|re)alloc`ed, so you should not `free` it in this case. But if you have `(m|c|re)alloc`ed memory to `test_struct->some_string`, you should `free` it before `free`ing `test_struct` or you'll leak memory. – Daniel Fischer Dec 27 '12 at 19:19

4 Answers4

6

Calling malloc(sizeof(struct some_struct)); gives you memory for your struct, which includes space for two integer fields and a pointer field.

The pointer field however cannot be used until it points to a valid location in memory. To do this, you need to point it to a valid memory location, by e.g. allocating memory for it with malloc or pointing it to a pre-existing valid memory location:

e.g.:

test_struct->some_string = malloc(100); // Allocate 100 bytes for the string
Charles Salvia
  • 52,325
  • 13
  • 128
  • 140
  • hello was wondering if you can comment on my new edited question, thanks :) – chutsu Dec 27 '12 at 19:03
  • 2
    @chutsu, anything you allocate with `malloc` must be free'd with `free()`. So if you allocate memory for `test_struct->some_string` using `malloc`, then yes you must also free it with `free`. But in your example code you just set `test_struct` to a string literal, which means you don't need to free it. – Charles Salvia Dec 27 '12 at 19:38
2

After running these two lines of code:

struct some_struct *test_struct;
test_struct = malloc(sizeof(struct some_struct));

You've done enough to start working with test_struct. A pointer's value is just a memory address so the malloc allocates enough for two ints and one char*. If you'd like to point test_struct->some_string at an already existing char* you may do so:

test_struct->some_string = some_other_char_pointer;

Otherwise, you'll need to allocate memory for it as well:

test_struct->some_string = malloc(...);
Foggzie
  • 9,691
  • 1
  • 31
  • 48
1

You may or may not need to allocate some memory for the string, depending on context. But the code you present allocate all the memory needed to hold that structure.

Basically, write code that does whatever it is you need to do. Whether you need memory for the string depends on what you're going to do.

With just the code you've shown, the pointer you allocated doesn't point to anything specific, just like the integers you allocated don't hold any specific values. Address allocation for the string, if needed, when you set the value of some_string to something useful, probably at the same time you set x and y to something useful.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
1

Ok, this bit of code is not doing what you want:

struct some_struct *test_struct = malloc(sizeof(some_string);
test_struct->x = 2;
test_struct->y = 3;
test_struct->some_string = "sadlfkajsdflk";

in this case, your *test_struct is now pointing to a 'memory zone' with the typeof some_sring size(I think your some_string is char*).

Malloc(X) gives you X space from your program (or process) virtual memory. When you do:

struct some_struct *test_struct; 

You get enough space to store a pointer to some_struct.

If you do:

malloc(sizeof(struct some_struct));

You have now reserved struct some_struct space from the virtual memory. But you want to know 'where' that memory is. Thats why you assign it to the pointer:

test_struct = malloc (sizeof(struct some_struct));

[EDIT]I'd write this:" To make your compiler happier you should also include a cast in there to tell the compiler that that space allocated by malloc is gonna be used to store a struct some_struct:", giving an example right after. But, in fact, that's not true. As you can see in the comments below, @chutsu corrected this, and to convince yourself, check this question. The 'main' reason is that you're taking a lot of risks in doing it for no advantages at all.
The rest of the code is now corrected: No cast.

A cleaner way to do this would've been typedefing the struct. Then, your code would look like this:

typedef struct some_struct {
    int x;
    int y;
    char *some_string;
}SomeStruct;

SomeStruct *test_struct;
test_struct = malloc(sizeof(SomeStruct));

About the string allocation. You can think like this: Everything created with malloc(and its brothers calloc, realloc...) needs to be free'd! This happens because all the other variables are local to functions, even the main is a function, and this ones are cleaned when the function terminates.

So, after allocating your struct, if you want space for your string, you'll have to allocate space for it.

test_struct->some_string = malloc((YOUR_STRING_SIZE+SPACE_FOR_THE_STRING_TERMINATOR)*sizeof(char));

with - SPACE_FOR_THE_STRING_TERMINATOR=1, the \0 character.

Then, if you want to free test_struct you'll have to free the string first and the struct later, in the reverse order you would lost the pointer to the string and that would leak. It looks like this:

free(test_struct->some_string);
free(test_struct);

And that's it, you're done.

Hope this helps.

Community
  • 1
  • 1
Afonso Tsukamoto
  • 1,184
  • 1
  • 12
  • 21
  • actually you don't put a cast infront of `malloc` in C. Have a look at a post I wrote here: http://chutsu.tumblr.com/post/38958361088/do-not-add-a-cast-to-malloc-when-programming-in-c – chutsu Dec 28 '12 at 01:43
  • What I get from that document is that you should'nt cast if you forget to include? I usually cast cause I know that I want it to assume that I know it is returning that type. [EDIT]Nice tumblr btw. – Afonso Tsukamoto Dec 28 '12 at 02:14
  • No its kind of the other way round, you shouldn't cast because you may forget to include. Admittedly the phrasing of the link is terrible. But essentially, with a C compiler if you put the cast the compiler assumes you know what you are doing. The problem is, if you forget to `#include ` and you have a cast infront of malloc, the compiler won't tell* you you forgot to include stdlib but give you other error messages that would be un-helpful. Check this [question](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) out :) – chutsu Dec 29 '12 at 17:38
  • 1
    Ah! Ok. That, actually, makes a lot of sense. This kind of things that you learn here are, in fact, pretty awesome!:) No teacher of mine have ever mentioned something like this, and they are always mentioning stuff like 'writing less code is the best way to avoid mistakes' and pointing out all the good programming practices. Thanks a lot @chutsu. Gotta edit my answer. – Afonso Tsukamoto Dec 29 '12 at 17:46