Maybe a bad topic, but given the following code, do i need to free(player->name) too?
#include <stdio.h>
struct Player
{
char *name;
int level;
};
int main()
{
struct Player *player;
player->name = malloc(sizeof(player->name)*256);
player->name = "John";
printf(player->name);
free(player);
printf("\n\n\n");
system("PAUSE");
return 0;
}
Oh boy, where to start? You really need a good book. Sigh. Let’s start at the top of
main():This
defines a pointer to a
struct Player, but it doesn’t initialize it. It has thus a more or less random value, pointing somewhere into memory. Thisnow writes into parts of that random location the address of a piece of memory obtained by
malloc(). Writing to memory through an uninitialized pointer invokes Undefined Behavior. After that, all bets are off. No need to look further down your program. You are unlucky that, by accident, you write to a piece of memory that is owned by your process, so it doesn’t crash immediately, making you aware of the problem.There’s two ways for you to improve that. Either stick to the pointer and have it point to a piece of memory allocated for a
Playerobject. You could obtain it by callingmalloc(sizeof(Player).Or just use a local, automatic (aka stack-based) object:
The compiler will generate the code to allocate memory on the stack for it and will release it automatically. This is the easiest, and should certainly be your default.
However, your code has more problems than that.
This
allocates consecutive memory on the heap to store 256 pointers to characters, and assigns the address of the first pointer (the address of a
char*, thus achar**) toplayer->name(achar*). Frankly, I’m surprised that even compiles, but then I’m more used to C++’ stricter type enforcement. Anyway, what you probably want instead instead is to allocate memory for 256 characters:(Since
sizeof(char)is, by definition,1, you will often see this asmalloc(256).)However, there more to this: Why 256? What if I pass a string 1000 chars long? No, simply allocating space for a longer string is not the way to deal with this, because I could pass it a string longer still. So either 1) fix the maximum string length (just declare
Player::nameto be achararray of that length, instead of achar*) and enforce this limit in your code, or 2) find out the length needed dynamically, at run-time, and allocate exactly the memory needed (string length plus 1, for the terminating'\0'char).But it gets worse. This
then assigns the address of a string literal to
player->name, overriding the address of the memory allocated bymalloc()in the only variable you store it in, making you lose and leak the memory.But strings are no first-class citizens in C, so you cannot assign them. They are arrays of characters, by convention terminated with a
'\0'. To copy them, you have to copy them character by character, either in a loop or, preferably, by callingstrcpy().To add insult to injury, you later attempt to free the memory a string literal lives in
thereby very likely seriously scrambling the heap manager’s data structures. Again, you seem to be unlucky for that to not causing an immediate crash, but the code seemingly working as intended is one of the worst possibilities of Undefined Behavior to manifest itself. If it weren’t for all bets being off before, they now thoroughly would be.
I’m sorry if this sounds condemning, it really wasn’t meant that way, but you certainly and seriously fucked up this one. To wrap this up:
You need a good C++ book. Right now. Here is a list of good books assembled by C programmers on Stack Overflow. (I’m a C++ programmer by heart, so I won’t comment on their judgment, but K&R is certainly a good choice.)
You should initialize all pointers immediately, either with the address of an existing valid object, or with the address of a piece of memory allocated to hold an object of the right type, or with
NULL(which you can easily check for later). In particular, you must not attempt to read from or write to a piece of memory that has not been allocated (dynamically on the heap or automatically on the stack) to you.You need to
free()all memory that was obtained by callingmalloc()exactly once.You must not attempt to
free()any other memory.I’m sure there is more to that code, but I’ll stop here. And did I mention you need a good C book? Because you do.