2014-01-21 4 views
1

У меня есть этот код, чтобы воспроизвести проблему, которую я имею в другом месте. Проблема в том, что я думаю, что создаю независимую копию набора символов и предоставляю им независимый указатель, но по какой-то причине я не понимаю, что компилятор уверен, что указатель указывает на источник копии.Почему освобождение скопированной памяти влияет на копию?

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

Если я не закомментировать свободный (a-> PTR) Я получаю строку, состоящую из квадратной коробки и некоторый случайный характер, в отличие от «Это строка».

Это C компиляция на mingw64.

+1

'printf (" Возвращенная строка b является% s \ n ", a-> ptr);' должно быть 'printf (" Возвращенная строка b является% s \ n ", b-> ptr);' Ошибка не в вашем коде Str. Вы просто печатаете не то. –

+0

Незначительный: предложите 'memcpy()', а не 'strncpy()', поскольку у вас есть полный размер. Также незначительно: чтобы уменьшить путаницу, подумайте о вызове поля 'len', когда это' size' строки, а не результат 'strlen()'. – chux

ответ

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

должно быть b->ptr?

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

Таким образом, вы можете сравнить не только содержание, но и адреса, что а> PTR и b-> PTR указывают на.

+0

Извините. Это было глупо со мной. Я до сих пор не смог воспроизвести проблему, которая у меня есть. – ste3e

Смежные вопросы