为什么释放复制的内存会影响副本?

时间:2014-01-21 03:17:11

标签: c pointers char

我有这个代码来重现我在其他地方遇到的问题。问题是我认为我正在创建一组字符的独立副本并提供一个独立的指针,但由于某种原因我不明白编译器确定指针指向副本的源。

#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;
}

如果我没有注释掉free(a-&gt; ptr),我会得到一个由方框和一些随机字符组成的字符串,而不是“This is a string”。

这是对mingw64的C编译。

2 个答案:

答案 0 :(得分:2)

else printf("Returned string b is %s\n", a->ptr);

应该是b->ptr吗?

答案 1 :(得分:2)

“为什么释放复制的内存会影响副本”这一问题的答案是“它没有”。如果你看到它几乎肯定意味着你在某个地方有一个迷路指针 - 要么你没有真正制作副本,要么你的副本在某种程度上被破坏了。

你的例子(虽然我确定它并没有真正反映你的问题)提供了一个很好的例子 - 你实际上是在打印错误的变量。这样:

else printf("Returned string b is %s\n", a->ptr);

应该是

else printf("Returned string b is %s\n", b->ptr);

在这种情况下,我经常发现打印指针本身很有用,以确保它确实指向我认为的缓冲区。例如:

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);

这样你不仅可以比较内容,还可以比较a-&gt; ptr和b-&gt; ptr指向的地址。