以不正确的方式使用 free 时崩溃
Crashing when using free in the incorrect way
typedef char* DString;
DString dstring_initialize(const char* str);
int dstring_concatenate(DString* destination, DString source);
void dstring_delete(DString* stringToDelete);
int main(void)
{
DString str1, str2;
str1 = dstring_initialize("hello ");
str2 = dstring_initialize("world");
dstring_concatenate(&str1, str2);
dstring_delete(&str1);
dstring_delete(&str2);
}
DString dstring_initialize(const char* str)
{
char* res = malloc(strlen(str) + 1);
if (res != NULL)
{
strcpy(res, str);
}
return res;
}
int dstring_concatenate(DString* destination, DString source)
{
DString newstr = realloc(*destination, ((strlen(*destination)+1)+ strlen((&source)+1))* sizeof *source);
if(newstr == NULL)
{
printf("Error");
}
strcat(newstr, source);
*destination = newstr;
return 1;
}
void dstring_delete(DString* stringToDelete)
{
assert(stringToDelete != NULL);
free(stringToDelete);
assert(*stringToDelete == NULL);
}
我怀疑是我分配错误或者分配内存的释放不正确,因为我调试代码的时候卡在了free(stringToDelete);
部分然后崩溃了。另一件事是我怀疑 realloc
部分不正确。任何帮助将不胜感激,如果问题很糟糕,请随时发表评论,以便我提高沟通技巧并进一步改进问题。
所以问题是您要向 dstring_delete 传递一个 DString* 类型的变量
然后你要求它释放它,但是如果我们查看 DString*,我们会发现它是 char**
但是在 dstring_initialize 等其他函数中,您分配了 char* 类型的 res
所以你要求编译器释放你从未分配的东西,这会导致你的代码崩溃:
这是新代码,检查它是否有效:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
typedef char* DString;
DString dstring_initialize(const char* str);
int dstring_concatenate(DString* destination, DString source);
void dstring_delete(DString stringToDelete);
int main(void)
{
DString str1, str2;
str1 = dstring_initialize("hello ");
str2 = dstring_initialize("world");
dstring_concatenate(&str1, str2);
dstring_delete(str1);
dstring_delete(str2);
}
DString dstring_initialize(const char* str)
{
char* res = malloc(strlen(str) + 1);
if (res != NULL)
{
strcpy(res, str);
}
return res;
}
int dstring_concatenate(DString* destination, DString source)
{
DString newstr = realloc(*destination, ((strlen(*destination)+1)+ strlen((&source)+1))* sizeof *source);
if(newstr == NULL)
{
printf("Error");
}
strcat(newstr, source);
*destination = newstr;
return 1;
}
void dstring_delete(DString stringToDelete)
{
assert(stringToDelete != NULL);
free(stringToDelete);
stringToDelete = NULL;
assert(stringToDelete == NULL);
}
还有一点free不会给释放的指针赋值NULL,它变成了垃圾数据,所以你需要先赋值为NULL再断言它是否为NULL
对于realloc
,仔细看这里:
strlen((&source)+1))
您正在将 char **
传递给 strlen
。你想要的是:
strlen(source)+1
整行是:
DString newstr = realloc(*destination, (strlen(*destination) + 1 +
strlen(source) + 1) * sizeof *source);
free
的问题是您传递的是已分配的内容。您而是在 main
中传递局部变量的地址。您需要取消引用:
free(*stringToDelete);
此外,释放内存不会将指针设置为 NULL,因此您应该删除 free
之后的 assert
。实际上,您也可以删除其他断言,因为将 NULL 指针传递给 free
已明确定义。
typedef char* DString;
DString dstring_initialize(const char* str);
int dstring_concatenate(DString* destination, DString source);
void dstring_delete(DString* stringToDelete);
int main(void)
{
DString str1, str2;
str1 = dstring_initialize("hello ");
str2 = dstring_initialize("world");
dstring_concatenate(&str1, str2);
dstring_delete(&str1);
dstring_delete(&str2);
}
DString dstring_initialize(const char* str)
{
char* res = malloc(strlen(str) + 1);
if (res != NULL)
{
strcpy(res, str);
}
return res;
}
int dstring_concatenate(DString* destination, DString source)
{
DString newstr = realloc(*destination, ((strlen(*destination)+1)+ strlen((&source)+1))* sizeof *source);
if(newstr == NULL)
{
printf("Error");
}
strcat(newstr, source);
*destination = newstr;
return 1;
}
void dstring_delete(DString* stringToDelete)
{
assert(stringToDelete != NULL);
free(stringToDelete);
assert(*stringToDelete == NULL);
}
我怀疑是我分配错误或者分配内存的释放不正确,因为我调试代码的时候卡在了free(stringToDelete);
部分然后崩溃了。另一件事是我怀疑 realloc
部分不正确。任何帮助将不胜感激,如果问题很糟糕,请随时发表评论,以便我提高沟通技巧并进一步改进问题。
所以问题是您要向 dstring_delete 传递一个 DString* 类型的变量 然后你要求它释放它,但是如果我们查看 DString*,我们会发现它是 char** 但是在 dstring_initialize 等其他函数中,您分配了 char* 类型的 res 所以你要求编译器释放你从未分配的东西,这会导致你的代码崩溃: 这是新代码,检查它是否有效:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
typedef char* DString;
DString dstring_initialize(const char* str);
int dstring_concatenate(DString* destination, DString source);
void dstring_delete(DString stringToDelete);
int main(void)
{
DString str1, str2;
str1 = dstring_initialize("hello ");
str2 = dstring_initialize("world");
dstring_concatenate(&str1, str2);
dstring_delete(str1);
dstring_delete(str2);
}
DString dstring_initialize(const char* str)
{
char* res = malloc(strlen(str) + 1);
if (res != NULL)
{
strcpy(res, str);
}
return res;
}
int dstring_concatenate(DString* destination, DString source)
{
DString newstr = realloc(*destination, ((strlen(*destination)+1)+ strlen((&source)+1))* sizeof *source);
if(newstr == NULL)
{
printf("Error");
}
strcat(newstr, source);
*destination = newstr;
return 1;
}
void dstring_delete(DString stringToDelete)
{
assert(stringToDelete != NULL);
free(stringToDelete);
stringToDelete = NULL;
assert(stringToDelete == NULL);
}
还有一点free不会给释放的指针赋值NULL,它变成了垃圾数据,所以你需要先赋值为NULL再断言它是否为NULL
对于realloc
,仔细看这里:
strlen((&source)+1))
您正在将 char **
传递给 strlen
。你想要的是:
strlen(source)+1
整行是:
DString newstr = realloc(*destination, (strlen(*destination) + 1 +
strlen(source) + 1) * sizeof *source);
free
的问题是您传递的是已分配的内容。您而是在 main
中传递局部变量的地址。您需要取消引用:
free(*stringToDelete);
此外,释放内存不会将指针设置为 NULL,因此您应该删除 free
之后的 assert
。实际上,您也可以删除其他断言,因为将 NULL 指针传递给 free
已明确定义。