Freeing memory, all? - c

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
struct Player *player;
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. This
player->name = malloc(sizeof(player->name)*256);
now 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 Player object. You could obtain it by calling malloc(sizeof(Player).
Or just use a local, automatic (aka stack-based) object:
struct Player player;
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
player->name = malloc(sizeof(player->name)*256);
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 a char**) to player->name (a char*). 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:
player->name = malloc(sizeof(char)*256);
(Since sizeof(char) is, by definition, 1, you will often see this as malloc(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::name to be a char array of that length, instead of a char*) 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
player->name = "John";
then assigns the address of a string literal to player->name, overriding the address of the memory allocated by malloc() 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 calling strcpy().
To add insult to injury, you later attempt to free the memory a string literal lives in
free(player);
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 calling malloc() 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.

You have to free() everything that you malloc() and you must malloc() everything that is not allocated at compile time.
So:
You must malloc player and you must free player->name

Ok, so your variable player is a pointer, which you have not initialized, and therefore points to a random memory location.
You first need to allocate the memory for player the way you have done for player->name, and then alocate for player->name.
Any memory allocated with malloc() needs to be freed with free().
Take a look at this and this.

This is awful code. Why? Firstly you allocate memory for player->name. malloc returns pointer to allocated memory. In next step you lose this pointer value because reassign player->name to point to static "John" string. Maybe you want to use strdup or sprintf functions?
Also the big mistake is to use uninitialized pointer to player struct. Try to imagine that it can point to random memory location. So it is good idea allocate memory for your structure with help of malloc. Or don't use pointer to structure and use real structure variable.

player doesn't need to be freed because it was never malloc'd, it's simply a local stack variable. player->name does need to be freed since it was allocated dynamically.
int main()
{
// Declares local variable which is a pointer to a Player struct
// but doesn't actually point to a Player because it wasn't initialised
struct Player *player;
// Allocates space for name (in an odd way...)
player->name = malloc(sizeof(player->name)*256);
// At this point, player->name is a pointer to a dynamically allocated array of size 256*4
// Replaces the name field of player with a string literal
player->name = "John";
// At this point, the pointer returned by malloc is essentially lost...
printf(player->name);
// ?!?!
free(player);
printf("\n\n\n");
system("PAUSE");
return 0;
}
I guess you wanted to do something like this:
int main() {
struct Player player;
player.name = malloc( 256 );
// Populate the allocated memory somehow...
printf("%s", player.name);
free(player.name);
}

Related

Overwriting global char array vs global char pointer in a loop in C

I have an infinite while loop, I am not sure if I should use a char array or char pointer. The value keeps getting overwritten and used in other functions. With a char pointer, I understand there could be a memory leak, so is it preferred to use an array?
char *recv_data = NULL;
int main(){
.....
while(1){
.....
recv_data = cJSON_PrintUnformatted(root);
.....
}
}
or
char recv[256] = {0};
int main(){
.....
while(1){
.....
strcpy(recv, cJSON_PrintUnformatted(root));
.....
}
}
The first version should be preferred.
It doesn't have a limit on the size of the returned string.
You can use free(recv_data) to fix the memory leak.
The second version has these misfeatures:
The memory returned from the function can't be freed, because you never assigned it to a variable that you can pass to free().
It's a little less efficient, since it performs an unnecessary copy.
Based on how you used it, the cJSON_PrintUnformatted returns a pointer to a char array. Since there are no input arguments, it probably allocates memory inside the function dynamically. You probably have to free that memory. So you need the returned pointer in order to deallocate the memory yourself.
The second option discards that returned pointer, and so you lost your only way to free the allocated memroy. Hence it will remain allocated -> memroy leak.
But of course this all depends on how the function is implemented. Maybe it just manipulates a global array and return a pointer to it, so there is no need to free it.
Indeed, the second version has a memory leak, as #Barmar points out.
However, even if you were to fix the memory leak, you still can't really use the first version of your code: With the first version, you have to decide at compile-time what the maximum length of the string returned by cJSON_PrintUnformatted(). Now,
If you choose a value that's too low, the strcpy() function would exceed the array bounds and corrupt your stack.
If you choose a value that's so high as to be safe - you might have to exceed the amount of space available for your program's stack, causing a Stack Overflow (yes, like the name of this site). You could fix that using a strncpy(), giving the maximum size - and then what you'd have is a truncated string.
So you really don't have much choice than using whatever memory is pointed to by the cJSON_PrintUnformatted()'s return value (it's probably heap-allocated memory). Plus - why make a copy of it when it's already there for you to use? Be lazy :-)
PS - What should really happen is for the cJSON_PrintUnformatted() to take a buffer and a buffer size as parameters, giving its caller more control over memory allocation and resource limits.

Is it possible to retrieve the start address from a pointer to allocated memory

It's known that you cannot in any standard way retrieve the allocated size of a memory block. For instance, if you do:
void *ptr = malloc(100);
There is no way to find out that it was 100 bytes allocated. But I started wondering if there is any way to do a similar thing, and that is retrieving the original pointer from a pointer pointing in that block. Like
void *ptr = malloc(100);
void *ptr2 = &ptr[10];
Can I in any way get ptr from ptr2 without knowing that it points at element 10?
I have not found a good use case for it, but something that is at least reasonable (and a little crazy) is if you want a function to allocate a string and return a pointer to the first digit in that string. I'm mostly just curious if it is possible.
Is it possible to retrieve the start address from a pointer to allocated memory
No. The details of allocation are an implementation detail, not specified by C. No portable way to find the size nor start from an arbitrary offsetted pointer alone.

C - memset vs free

I am confused on what actually happens in memory when memset is called versus what happens when you call free.
For example I have a pointer A that points to an array of char*'s
char** A = (char**)calloc(5, sizeof(char*));
int i;
for(i=0;i<5;i++)
{
//filling
A[i] = (char*)calloc(30, sizeof(char));
scanf("%s", &A[i]);
}
now I want to reset it my char** pointer and all the elements
it points to be completely empty
memset(A, 0, 5);
or
free(A);
what is the difference?
I am somewhat new to C so please speak in layman's terms thank you
The difference is that memset actually sets the value of a block of memory, while free returns the memory for use by the operating system.
By analogy using physical things, memset(beer, 0, 6) applied to a six-pack of beer would apply the value of '0' to all six members of the array beer, while free(beer) would be the equivalent of giving the six-pack away to a friend.
The memset function sets an area of memory to the requested value. Do note that the size you provide is the number of bytes.
The free function releases the allocated memory so it can't be used anymore. Calling free doesn't usually modify the memory in any way. Using the memory after calling free leads to undefined behavior.
Both approaches are incorrect, but somewhat complementary.
memset will set the content of the buffer to the given value, 0 in your case. This will change the value of the pointers, which will cause you to lose the references to the allocated buffers (in each A[i]).
free(A) will release the buffer pointed by A, but this buffer contains pointers, and each of the buffers that is pointed by them will not be freed.
in short - memset does not free a dynamically allocated buffer, and free does not set it to zero.
A correct approach will be something like that:
for(i=0;i<5;i++)
{
// complementary to
// A[i] = (char*)calloc(30, sizeof(char));
free(A[i]);
}
// complementary to
// char** A = (char**)calloc(5, sizeof(char*));
free(A);
A = NULL; // so no one gets confused...
free deallocates the memory, which means A would still be pointing to the same memory location, which is invalid now.
memset will set the memory currently pointed to by A, to whatever you want.
memset changes the contents at the memory address. It does not alter whether the memory is allocated/deallocated.
free does not change the contents at the memory address. It deallocates the block of memory which makes it available for the program to reclaim and reuse. Therefore any pointers to this block become invalid and trying to access the memory should result in a Segfault ("if you're lucky" as my professor would say).
Use memset when you know you are going to be accessing the data at that address again. Use free when you know that the data will no longer be accessed ever again and that the program may reclaim that memory.
memset() method just replaces the x memory bytes with a given character the allocated memory which is pointed by a pointer *a;
memset(a, 'a', x);
The prototype of memset() method is:
void* memset(void*, unsigned int, int);
memset() behaves like strcpy() but the difference is that memcpy() copied the data as it is (byte), but strcpy copies the formatted string as well (so takes more time than memcpy to execute).
However, free() method just deallocates the memory space and makes it available to get occupied.
While other answers explain the difference, let me add an example when both memset() and free() will need to be used together, in a specific order:
If the malloc'ed memory region was used to store any critical/valuable information that needs to be erased to prevent others from snooping on it (say some security-related stuff like managing a password or some other crypto), you would want to first erase the contents in that memory region and then call free() on it to give away that region's control back to the OS.
Hence, just like free() is the opposite of malloc(), memset(to zero)-then-free() is the opposite of calloc().

Where the char* is pointing to?

I have some very basic questions regarding pointers and memory allocation.
In below code where does pointer c actually point to? In other words where does the string "xyz" get stored in memory (stack/heap etc.)?
What will happen to memory location allocated for a as I am not using it anymore?
Code seems to work well if I un-comment the commented section. What's happening with the memory in that scenario?
#include <stdio.h>
main()
{
char *c;
//c = (char *)malloc(2);
c = "a";
c = "xyz" ;
printf("%s",c);
return 0;
}
Output:
xyz
Edit:
After reading few of the answer and first comment another question came up in my mind:
In below case, where do the strings get stored? Can I alter them later on?
char *c[] = {"a","xyz"};
The specific details are implementation dependent, but in most common implementations, literal strings like "a" and "xyz" are stored in the text section of the program, like the machine code that implements the program. Assigning a = "xyz"; sets a to point to that location in memory.
The memory for "a" is unaffected. However, an optimizing compiler may notice that c was never used between that assignment and being reassigned, so it could simply ignore the first assignment, and never allocate any space for "a" at all.
The memory you allocated with malloc() stays allocated until the program ends. Allocating memory without freeing it is called a memory leak, and you should try to avoid it.
1.In below code where does pointer 'c' is actually pointing to?In other words where does the string "xyz" get stored in memory(stack/heap etc.)?
will place xyz the read-only parts of the memory and making c a pointer to that, a variable of type pointer-to-char, called c , which is initialized with the location of the first character in that unnamed, read-only array.you created automatic storage (often called the stack). Here you just point to memory in text section.
2.What will happen to memory location allocated for"a"' as i am not using it anymore?
As per your code you not allocated any memory just you assign string literals to that.If you allocate then need to free it.
3.Code seems to work well if I un-comment the commented section.Whats happening with memory in that scenario?
If you un comment the allocation statement to allocate memory then also it point to you literal string but you need to free that memory.
Now for case
char *c[] = {"a","xyz"};
when you declare and initialize words, it'll be allocated on the stack as any other automatic array and its items will be assigned to pointers to the beginning of each string constant.Also to alter this string may illegal.
"xyz" and "a" are string literals which is mostly available in string table.
"xyz" is printed because it is recently assigned to that pointer.
To a place in the heap/stack in the READ-ONLY part of the memory which the string is in. When assigning a string literal directly into a pointer, the program searches for that string in the memory, if it exists through the short search he's doing, it'll point to it, if it doesn't - it will create it. Either way it's read only so it'll be the same as a const char* so you can't change it (of course you can somehow manipulate it, maybe by another pointer or so).
Nothing, it'll stay unaffected.
What's happening is that malloc returns a pointer and you just ignore it, you go to another address containing a and it will not have the same influence as strcpy(c, "a"); as you ignore the allocated memory and its pointer - you do not free it. Generally, nothing's happen if you don't free the memory (I mean, at the end of the program it is freed automatically by the OS) but it WILL take memory within the program so if i'd allocate, let's say 1000000 bytes (assuming it succeeded), allocating more heap memory would be a problem :P
about the other question... You can't alter them through that pointer, try and it will throw an interrupt in the middle of the program and it'll probably stop responding.

malloc preventing garbage from being printed?

Program was programmed in C and compiled with GCC.
I was trying to help a friend who was trying to use trying to (shallow) copy a value that was passed into a function. His the value was a struct that held primitives and pointers (no arrays or buffers). Unsure of how malloc works, he used it similar to how the following was done:
void some_function(int rand_params, SOME_STRUCT_TYPEDEF *ptr){
SOME_STRUCT_TYPEDEF *cpy;
cpy = malloc(sizeof(SOME_STRUCT_TYPEDEF));// this line makes a difference?!?!?
cpy = ptr;// overwrites cpy anyway, right?
//prints a value in the struct documented to be a char*,
//sorry couldn't find the documentation right now
}
I told him that the malloc shouldn't affect the program, so told him to comment it out. To my surprise, the malloc caused a different output (with some intended strings) from the implementation with the malloc commented out (prints our garbage values). The pointer that's passed into the this function is from some other library function which I don't have documentation for at the moment. The best I can assume it that the pointer was for a value that was actually a buffer (that was on the stack). But I still don't see how the malloc can cause such a difference. Could someone explain how that malloc may cause a difference?
I would say that the evident lack of understanding of pointers is responsible for ptr actually pointing to memory that has not been correctly allocated (if at all), and you are experiencing undefined behaviour. The issue is elsewhere in the program, prior to the call to some_function.
As an aside, the correct way to allocate and copy the data is this:
SOME_STRUCT_TYPEDEF *cpy = malloc(sizeof(SOME_STRUCT_TYPEDEF));
if (cpy) {
*cpy = *ptr;
// Don't forget to clean up later
free(cpy);
}
However, unless the structure is giant, it's a bit silly to do it on the heap when you can do it on the stack like this:
SOME_STRUCT_TYPEDEF cpy = *ptr;
I can't see why there difference in the print.
can you show the print code?
anyway the malloc causes memory leak. you're not supposed to allocate memory for 'cpy' because pointer assignment is not shallow-copy, you simply make 'cpy' point to same memory 'ptr' point by storing the address of the start of that memory in 'cpy' (cpy is mostly a 32/64 bit value that store address, in case of malloc, it will store the address of the memory section you allocated)

Resources