1
 struct TokenizerT_ {
    char* separators;
    char* tks;
    char* cur_pos;
    char* next;
  };

  typedef struct TokenizerT_ TokenizerT;

  TokenizerT *TKCreate(char *separators, char *ts) 
  { 
    TokenizerT *tokenizer;
    tokenizer = (TokenizerT*)malloc(sizeof(TokenizerT));

    //some manipulation here

    tokenizer->tks = (char*) malloc (strlen(str)* sizeof(char));
    tokenizer->tks=str;
    printf("size of tokenizer->tks is %zu\n", strlen(tokenizer->tks)); //this prints out the correct number (e.g. 7)
    return tokenizer;
  }

  int main(int argc, char **argv)
  {
    TokenizerT *tk = TKCreate(argv[1], argv[2]);
    printf("tk->tks: %zu\n", strlen(tk->tks)); //HOWEVER, this prints out the wrong number (e.g. 1)
  }

从上面的代码可以看出,我正在使用指向结构的指针。出于某种原因,我没有收到 tk->tks 的正确长度。我无法理解这一点,因为它应该与我的 TKCreate 函数中的 tks 大小相同。有人可以解释一下吗?

4

3 回答 3

2

我怀疑 str(其定义未显示在您的代码片段中)是 TKCreate() 中定义的局部变量。如果是这样,您将分配 tokenizer->tks 以具有 str 的值,该值指向 TKCreate() 范围内的正确字符串,但在退出 TKCreate() 时,堆栈内容(包括参数和局部变量)被释放并消除了,因此当您尝试在 TKCreate() 范围之外引用该指针时,所有赌注都已关闭。

一个合理的解决方法是动态地为 tokenizer->tks 分配存储,因此它在退出 TKCreate() 后仍然存在。我看到你通过调用 malloc 来做到这一点,但是你用 str 的显式赋值覆盖了它。相反,您应该通过以下方式将 str 的内容(使用 strcpy)复制到动态分配的内存中: strcpy(tokenizer->tks, str);

于 2012-09-26T05:41:21.183 回答
0

您应该使用tostrcpy的内容,因为当您使用分配运算符时,您会丢失给您的指针,造成内存泄漏并指向局部变量,该变量将在函数返回后被销毁。strtokenizer->tksmalloctokenizer->tks

因此,该方法将是这样的:

tokenizer->tks = (char *)malloc ((strlen(str) + 1) * sizeof(char));
strcpy(tokenizer->tks, str);

另一件事:

在你释放自己之前不要忘记。free ->tks tk

因此,在 printf 之后,您应该使用:

free(tk->tks);
free(tk);

如果你的程序那么小,那么不释放结构和字符串(它在另一个内存位置而不是在结构的内存空间内,这就是为什么你必须释放它们)没有问题,因为在它执行之后,程序的无论如何,记忆都会被抹去。但是如果你打算在一个完整的大程序上实现这个功能,释放内存是一个很好的动作。

于 2012-09-26T05:49:40.240 回答
0

目前尚不清楚在哪里str定义,但如果它是函数中的局部变量,您的问题很可能超出范围,因此数据被覆盖。

您正在泄漏内存,因为您忘记使用strcpy()ormemcpy()memmove()将值复制到str分配的空间中,并且您用指针覆盖了指向新分配内存的唯一指针str。如果您复制,您将超出范围,因为您忘记为尾随的 null 和字符串分配足够的空间。您还应该检查分配是否成功。

伪代码:

tokenizer->tks = (char*) malloc (strlen(str)* sizeof(char));
tokenizer->tks = str;

固定代码:

size_t len = strlen(str) + 1;
tokenizer->tks = (char *)malloc(len);
if (tokenizer->tks == 0)
    ...error handling...
memmove(tokenizer->tks, str, len);

使用memmove()ormemcpy()可以轻松胜过strcpy()(请参阅为什么 Python 比 C 更快以获取一些说明和时序)。有些人会因为在 上使用演员表而责备你(和我)malloc();我理解他们为什么会这样争论,但我并不完全同意他们的观点(而且通常自己使用演员表)。因为sizeof(char)根据定义是 1,所以没有特别需要乘以它,尽管这样做也没有什么害处。

于 2012-09-26T06:00:13.867 回答