I have a struct
struct request { int code; char *message; };
that I'd like to free properly.
I have the following function to do that:
void free_request(struct request *req) { if (req->message != NULL) { free(req->message); } free(req); req = NULL; }
The problem is that I get an "free(): invalid pointer"/segfault error from the compiler when I try to free a request that has been created using a string literal:
struct request *req; req = malloc(sizeof(struct request)); req->message = "TEST"; free_request(req);
Since I want to create request structs in different places, once using literals (on the client side) and once using *chars that I read from a socket (on the server side) I was wondering if there is a function to make sure that I don't try to free the literals while still allowing me to free the message I have created using a malloc.
The 'char *' doesn't magically create a string, it really is just a pointer (to a single character).
A "string literal" is a sequence of characters from the source character set enclosed in double quotation marks (" "). String literals are used to represent a sequence of characters which, taken together, form a null-terminated string. You must always prefix wide-string literals with the letter L.
String literals are passed to functions as pointers to a stored string. For example, given the statement: printf( "Please enter a positive value for the angle: " );
Of course it is, a string literal is of array type. It is converted to a pointer to char in the expression and is like an any pointer to char . char *p = "abc"; char c = p[1];
There is no standard function that lets you know if a pointer was dynamically allocated or not. You should include a flag in your struct to inform yourself of it, or only use dynamically allocated strings (strdup
is your friend in this case). Depending on your networking setup, it might be simpler to use strdup
(well, to tell the truth, it is simpler to use the strdup
at all).
With strdup
:
struct message* req; req = malloc(sizeof *req); req->message = strdup("TEST"); free_request(req);
With a flag:
struct message { int code; char* message; bool isStatic; // replace to 'char' if bool doesn't exist }; void free_request(struct message* req) { if (!req->isStatic) free(req->message); free(req); } struct message* req; req = malloc(sizeof *req); req->message = "TEST"; req->isStatic = 1; free_request(req);
Also, don't forget to zero your allocated memory when you create an object. That could save you a lot of trouble.
req = malloc(sizeof *req); memset(req, 0, sizeof *req);
That, and setting req
to NULL
from free_request
won't have any effect. You either need to take a struct message**
or do it yourself after the function calls.
There is no way to tell if you are using a string literal (Well, you can put string literals in a custom .section created by GCC, and then examine the string pointer to determine if it is contained in the .section of literals). However...there is a better way using a simple programming pattern.
Normal case. A call to free(req) will work as expected: freeing the request structure.
struct *req; req = malloc(sizeof(*req)); req->message = "TEST";
In the following, some_string
is a string you wish to store as the request message. It can be either a literal, or a dynamically allocated. This allocates memory for the string when the struct itself is allocated (and will be freed automatically when the struct is freed).
struct *req; req = malloc(sizeof(*req)+strlen(some_string)+1); req->message = (char *)&req[1]; strcpy(req->message, some_string);
free(req);
Note that the allocation scheme above for the dynamic string
is general, it can be used even when you don't know if some_string
is a literal or not. Thus, a single function that takes care of both cases, and freeing with free()
rids you of special cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With