Reputation: 1045
I have this code to reproduce the problem I am having elsewhere. The problem is that I think I am creating an independent copy of a set of characters and providing an independent pointer to them, but for some reason I do not understand the compiler is certain that the pointer is pointing to the source of the copy.
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
typedef struct Str{
size_t len;
char* ptr;
}Str;
Str* newStr(char* str);
Str* cpyStr(Str* str);
int main(int argc, char *argv[]){
Str* a = newStr("This is a string");
printf("Returned string a is %s\n", a->ptr);
Str* b = cpyStr(a);
//free(a->ptr);
//free(a);
if(b == NULL) puts("Error getting b");
else printf("Returned string b is %s\n", a->ptr);
return 0;
}
Str* newStr(char* str){
size_t len = strlen(str) + 1;
if(len == 0) return NULL;
Str* toret = malloc(sizeof(Str));
if(toret == NULL) return NULL;
toret->len = len;
toret->ptr = malloc(len * sizeof(char));
if(toret->ptr == NULL) return NULL;
strncpy(toret->ptr, str, len);
return toret;
}
Str* cpyStr(Str* str){
Str* toret = malloc(sizeof(Str));
if(toret == NULL) return NULL;
toret->len = str->len;
printf("Len is %d\n", toret->len);
toret->ptr = malloc(toret->len * sizeof(char));
if(toret->ptr == NULL) return NULL;
strncpy(toret->ptr, str->ptr, toret->len);
return toret;
}
If I do not comment out the free(a->ptr) I get a string consisting of a square box and some random character as opposed to "This is a string".
This is C compiling on mingw64.
Upvotes: 1
Views: 75
Reputation: 30597
The answer to the question "why does freeing copied memory affect the copy" is "it doesn't". If you are seeing this it almost certainly means you have a stray pointer somewhere - either you aren't really making a copy, or your copy is becoming corrupted some other way.
Your example (although I'm sure it doesn't really reflect your problem) provides a good example - you are actually printing the wrong variable. This:
else printf("Returned string b is %s\n", a->ptr);
Should be
else printf("Returned string b is %s\n", b->ptr);
In such cases I often find it useful to print out the pointer itself, to make sure it really is pointing to the buffer I think it is. For example:
printf("Returned string a(%p) is %s\n", a->ptr, a->ptr);
...
else printf("Returned string b(%p) is %s\n", b->ptr, b->ptr);
That way you can compare not only the contents but the addresses of that a->ptr and b->ptr are pointing to.
Upvotes: 2
Reputation: 4332
else printf("Returned string b is %s\n", a->ptr);
should it be b->ptr
?
Upvotes: 2