使用其他功能解决C中的内存问题

时间:2014-02-03 19:28:47

标签: c

我正在创建一个程序,通过这个过程创建一个结构:

TokenizerT *TKCreate(char *separators, char *ts) {
    TokenizerT * inu = malloc(sizeof(*inu));
    char * sts = malloc(strlen(ts)*sizeof(char));
    char * by = malloc(lim*sizeof(char));
    strcpy(by, yr);
    strcpy(sts, ts);
    inu->sep = by;
    inu->toks = sts;
    return inu;
}

我需要通过另一个函数释放struct inu,但我的函数下面似乎只释放与TokenizerT.sep相关的内存

void TKDestroy(TokenizerT *tk) {
    free(tk->sep);
    free(tk->toks);
}

如何释放tk.sep和tk.toks?

编辑:free(tk)导致此错误:“malloc: *对象0x7fff55662bd8的错误:释放的指针未分配 * 在malloc_error_break中设置断点以调试“

EDIT2:结构定义

struct TokenizerT_ {
char * sep;
char * toks;
};

并且

void TKDestroy(TokenizerT *tk) {
    free(tk->sep);
    free(tk->toks);
    free(tk);
}

导致编辑1

中指定的错误相同

编辑3:我还添加了我的主要方法:

int main(int argc, char **argv) {

char * arr = argv[1];
char * y = argv[2];
TokenizerT jer = *TKCreate(arr, y);
TKDestroy(&jer);

return 0;
}

4 个答案:

答案 0 :(得分:1)

首先,“inu”的malloc似乎不正确

TokenizerT * inu = malloc(sizeof(inu));

我相信它只能获得4个字节的内存(在32位系统中)

应该是:

TokenizerT * inu = malloc(sizeof(TokenizerT ));

正如你所提到的 - “我需要释放struct inu”

我认为分配的“inu”被传递到“TKDestroy(TokenizerT * tk)”

然后:

void TKDestroy(TokenizerT *tk) {
    free(tk->sep);
    free(tk->toks);
    free(tk) // this free is what you want to free "inu"

答案 1 :(得分:0)

您只需要反转您为分配所做的操作:

void TKDestroy(TokenizerT *tk) {
    free(tk->sep);  // for the 3rd malloc()
    free(tk->toks); // for the 2nd malloc()
    free(tk);       // for the 1st malloc()
}

BTW:根据定义,您知道sizeof(char)总是1吗?


错误分配tk会导致错误 - 您只是为指针分配了足够的内存,而不是整个结构。这会搞砸。

答案 2 :(得分:0)

关于你的主,替换:

TokenizerT jer = *TKCreate(arr, y);
TKDestroy(&jer);

使用:

TokenizerT *jer = TKCreate(arr, y);
TKDestroy(jer);

原因是你的create-function返回一个指针,然后你将它传递给你的destroy-function ......

答案 3 :(得分:0)

您的代码因该错误而失败的原因是&jer是本地变量的地址。它是malloc调用返回的非地址。

TokenizerT jer = *TKCreate(arr, y);
TKDestroy(&jer);

因此,jer是一个局部变量。 TKCreate返回的地址会立即被取消引用,并且会生成结构的副本。您只是无法保留TKCreate返回的地址而且已泄露。然后,当您尝试在&jer上自由呼叫本地变量的地址时,您的环境会正确地报告您正在向free传递一个地址,该地址不是通过调用malloc创建的

正如我在上一个问题中所说的,按值返回结构比使用动态分配更有意义。最重要的是,您的字符串分配不正确。您必须始终为null终止符分配足够的空间。

我会写这样的程序:

#include <stdlib.h>
#include <string.h>

typedef struct {
    char *sep;
    char *toks;
} TokenizerT;

TokenizerT TKCreate(const char *seps, const char *toks) 
{
    TokenizerT inu;

    inu.sep = malloc(strlen(seps)+1);
    strcpy(inu.sep, seps);

    inu.toks = malloc(strlen(toks)+1);
    strcpy(inu.toks, toks);

    return inu;
}

void TKDestroy(TokenizerT *tk) 
{
    free(tk->sep);
    free(tk->toks);
}

int main(int argc, char **argv) 
{
    TokenizerT jer = TKCreate(argv[1], argv[2]);
    TKDestroy(&jer);
    return 0;
}

备注:

  1. 根据定义,sizeof(char)1所以成语要求在调用malloc()时将其作为乘法因素省略。
  2. 我已将TKCreate的参数赋予与struct字段相同的名称。这使得更容易理解发生了什么。更重要的是,你的代码看起来很简单,因为它忽略了其中一个参数。
  3. 如上所述,struct按值返回。这在概念上更容易处理。

  4. 您可能更喜欢编写辅助函数来复制字符串。如果编译器的运行时已经有一个名为strdup的函数,那么您可以使用它。否则你可以使用这个简单的实现:

    char *strdup(const char *str)
    {
        char *result = malloc(strlen(str)+1);
        strcpy(result, str);
        return result;
    }
    

    如果你只想在这样写的时候搜索null-terminator:

    char *strdup(const char *str)
    {
        size_t len = strlen(str)+1;
        char *result = malloc(len);
        memcpy(result, str, len);
        return result;
    }
    

    然后代码变为:

    #include <stdlib.h>
    #include <string.h>
    
    char *strdup(const char *str)
    {
        size_t len = strlen(str)+1;
        char *result = malloc(len);
        memcpy(result, str, len);
        return result;
    }
    
    typedef struct {
        char *sep;
        char *toks;
    } TokenizerT;
    
    TokenizerT TKCreate(const char *seps, const char *toks) 
    {
        TokenizerT inu;
        inu.sep = strdup(seps);
        inu.toks = strdup(toks);
        return inu;
    }
    
    void TKDestroy(TokenizerT *tk) 
    {
        free(tk->sep);
        free(tk->toks);
    }
    
    int main(int argc, char **argv) 
    {
        TokenizerT jer = TKCreate(argv[1], argv[2]);
        TKDestroy(&jer);
        return 0;
    }
    

    如果您急于返回指向结构的指针,请按以下方式执行:

    #include <stdlib.h>
    #include <string.h>
    
    char *strdup(const char *str)
    {
        size_t len = strlen(str)+1;
        char *result = malloc(len);
        memcpy(result, str, len);
        return result;
    }
    
    typedef struct {
        char *sep;
        char *toks;
    } TokenizerT;
    
    TokenizerT *TKCreate(const char *seps, const char *toks) 
    {
        TokenizerT *inu = malloc(sizeof *inu);
        inu->sep = strdup(seps);
        inu->toks = strdup(toks);
        return inu;
    }
    
    void TKDestroy(TokenizerT *tk) 
    {
        free(tk->sep);
        free(tk->toks);
        free(tk);
    }
    
    int main(int argc, char **argv) 
    {
        TokenizerT *jer = TKCreate(argv[1], argv[2]);
        TKDestroy(jer);
        return 0;
    }
    

    请特别注意我调用TKCreateTKDestroy的方式的不同。

    最后,我忽略了对malloc()调用的所有错误检查。在实际的生产代码中,你不会这样做,但为了清楚地说明,最好在这里省略它。