4

我一生都无法弄清楚我做错了什么。

T* tokenizer = create(argv[1], argv[2]);
destroy(tokenizer);

这是结构:

struct T_
{
    char *sep_set;
    char *str;
    char *token;
    int *last_index;
};
typedef struct T_ T;

这是创建函数:

T *create(char *separators, char *ts)
{
    T *tk = malloc(sizeof(struct T_));
    tk->sep_set = malloc(sizeof(char)*strlen(separators));
    tk->str = malloc(sizeof(char)*strlen(ts));
    tk->last_index = malloc(sizeof(int));
    tk->sep_set = separators;
    tk->str = ts;
    *tk->last_index = 0;
    return tk;
}

void destroy(T *tk)
{
    free(tk->sep_set);
    free(tk->str);
    free(tk->last_index);
    free(tk);
}

我的错误是:

==12302== Invalid free() / delete / delete[] / realloc()
==12302==    at 0x4C273F0: free (vg_replace_malloc.c:446)
==12302==    by 0x400649: destroy (t.c:58)
==12302==    by 0x40088C: main (t.c:145)
==12302==  Address 0x7ff0006e7 is on thread 1's stack
==12302== 
==12302== Invalid free() / delete / delete[] / realloc()
==12302==    at 0x4C273F0: free (vg_replace_malloc.c:446)
==12302==    by 0x400659: destroy (t.c:59)
==12302==    by 0x40088C: main (t.c:145)
==12302==  Address 0x7ff0006ec is on thread 1's stack

第 58 和 59 行是

free(tk->sep_set);
free(tk->str);

任何帮助将非常感激!

4

3 回答 3

4

Your grasp of strings in C seems to be failing you.

This:

tk->sep_set = malloc(sizeof(char)*strlen(separators));
tk->sep_set = separators;

is wrong, it overwrites the pointer returned by malloc() with the separators argument pointer, dropping the handle to the memory which is leaked. The wrong pointer is then passed to free(), which is invalid.

It should be:

tk->sep_set = strdup(separators);

if you have it, else:

if((tk->sep_set = malloc(strlen(separators) + 1)) != NULL)
    strcpy(tk->sep_set, separators);

Some points:

  1. You must add 1 to the length to make room for the '\0' terminator.
  2. You don't need to "scale" by sizeof (char), that's guaranteed to be 1 so it's just clutter.
  3. You must check that malloc() doesn't fail.
  4. You must copy strings with strcpy().

The same is true for the str field (with the ts argument).

于 2013-09-11T16:43:24.670 回答
2

尝试更换

tk->sep_set = malloc(sizeof(char)*strlen(separators));
tk->str = malloc(sizeof(char)*strlen(ts));
tk->sep_set = separators;
tk->str = ts;

tk->sep_set = strdup(separators);
tk->str = strdup(ts);
于 2013-09-11T16:46:20.823 回答
1

这已解决,但我想澄清一些事情,因为我在 Valgrind 日志中收到很多“大小为 n 的无效写入”错误。我以为我使用了太多的堆栈空间,但事实并非如此。

如果您调用 fprintf 并将输出定向到 stderr,所有这些调用都将显示在 Valgrind 中。伙计,他们会填满你的日志吗?一次 fprintf 调用产生了大约 300 个这样的错误。

例如

    fprintf(stderr,"I want to print %d and %d", num1, num2);

将填满你的 Valgrind 日志。我担心有什么严重的问题,我找不到我的问题。事实证明,没有任何问题,我只是浪费了过去的 45 分钟。

于 2014-10-02T23:55:56.350 回答