3

In the program I am working on I have a struct like

typedef struct _mystruct{
    char* my_string;
} mystruct;

Most of the time the time my_string is allocated using malloc, so there is a function that calls

free(mystructa->my_string);  

Generally this works, but at some points, my_string is set as a literal

my_string = "This is a literal"; 

Is there a way to tell the difference between the two before my call to free()?

user3386109
  • 34,287
  • 7
  • 49
  • 68
Graeme
  • 43
  • 4
  • 6
    No reliable/portable way that I know of. – John3136 Mar 04 '15 at 23:16
  • Check out the second answer... http://stackoverflow.com/questions/9504588/should-i-free-char-initialized-using-string-literals - "Ideally, malloc() calls and free() calls should appear on the same "design level" (inside the same implementation file for the same module for example), and they should match perfectly: one free() for each malloc()" – Alex Mar 04 '15 at 23:19
  • 4
    You shouldn't solve your problem from that end. Better to use ownership pattern: every object that is stored in memory (by pointer) should be owned by some part of a program. Buffers inside structs fields are usually owned by that structs, so 1) you should always assign dynamically allocated buffers to struct fields (never static strings) and 2) you should always free memory when struct is disposed. – rutsky Mar 04 '15 at 23:23
  • 4
    This question has detailed answer about how objects are stored in memory and why this task is not solvable: https://stackoverflow.com/questions/16360620/find-out-whether-a-pointer-is-pointing-at-the-stack-heap-or-program-text – rutsky Mar 04 '15 at 23:25
  • 3
    i would always strdup the string so that I own the string I am encapsulating. THen if the caller passes a local, const, static all work, even if they pass heap string and later free it – pm100 Mar 04 '15 at 23:29
  • It seems like my best solution is to make a copy of any string that gets set so that its always the same. Thanks – Graeme Mar 04 '15 at 23:46
  • Plus 1 to @rutsky's answer. This shouldn't be an issue. Whatever allocates it should be responsible for deallocating it. – Qix - MONICA WAS MISTREATED Mar 04 '15 at 23:47

2 Answers2

7

There is no way to reliably distinguish between a pointer to a literal and a pointer to allocated memory. You will have to roll your own solution. There are two ways to approach this:

1) Set a flag in the struct indicating whether the pointer should be freed.

typedef struct _mystruct {
    char *my_string;
    int string_was_allocated;
} mystruct;

mystructa.my_string = malloc(count);
mystructa.string_was_allocated = 1;
.
.
if (mystructa.string_was_allocated)
   free(mystructa.my_string);

mystructa.my_string = "This is a literal";
mystructa.string_was_allocated = 0;

2) Always dynamically allocate using strdup.

mystructa.my_string = strdup("This is a literal");
free(mystructa.my_string);

Both approaches involve changes to existing code, but I think solution 2 is much more robust, reliable and maintainable.

Carey Gregory
  • 6,836
  • 2
  • 26
  • 47
-3

Dynamic memory and static memory go to separate places: stack and heap

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char* argv[]) {

char aString[] = "this is a string";

printf("the string is located at %x \n", &aString);


char * pString = (char*) malloc(sizeof(char) * 64);
strcpy(pString, "this is a dynamic string");

printf("the pointer is located at %x \n", &pString);

printf("the dynamic string is located at %x \n\n", &*pString);



return 0;
}

/************* *** **************/

robert@debian:/tmp$ gcc test.c 
robert@debian:/tmp$ ./a.out
the string is located at bfcdbe8f 
the pointer is located at bfcdbe88 
the dynamic string is located at 95a3008 
mrflash818
  • 930
  • 13
  • 24