【问题标题】:Crashing when using free in the incorrect way以不正确的方式使用免费时崩溃
【发布时间】:2021-08-04 06:19:53
【问题描述】:
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 部分不正确。任何帮助将不胜感激,如果问题很糟糕,请随时发表评论,以便我提高沟通技巧并进一步改进问题。

【问题讨论】:

    标签: c string malloc realloc double-pointer


    【解决方案1】:

    所以问题是您正在向 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

    【讨论】:

      【解决方案2】:

      对于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 是明确定义的。

      【讨论】:

      • 我仍然会崩溃,Process returned -1073741819 (0xC0000005) 并且每当我调试它时,代码块都无法越过free(*stringToDelete);
      • @Darke 它对我来说在 valgrind 中运行干净。您是否完全复制上方的realloc 行?
      • 是的,它现在运行了,因为愚蠢的评论它是 ; : problem 我放错了列
      猜你喜欢
      • 1970-01-01
      • 2012-03-29
      • 1970-01-01
      • 2022-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多