我正在努力实现一项作业的 tail 。我让它工作正常,但我似乎随机地从免费中收到错误。

我看不出,追踪它的模式或除它之外的任何东西是一致的。

例如,如果我将我的程序称为“tail -24 test.in”,我会在多次运行的同一行中收到错误的校验和错误。然而,对于不同的文件,甚至不同的打印行数,我将毫无错误地返回。

关于如何追踪问题的任何想法,我已经尝试调试了几个小时但无济于事。

这是有问题的代码:

lines 被定义为 char** 并被 malloc 为:

lines = (char**) malloc(nlines * sizeof(char *));

void insert_line(char *s, int len){

  printf("\t\tLine Number: %d Putting a %d line into slot: %d\n",processed,len,slot);
  if(processed > numlines -1){//clean up
    free(*(lines+slot));
    *(lines + slot) = NULL;
  }
  *(lines + slot) = (char *) malloc(len * sizeof(char));
  if(*(lines + slot) == NULL) exit(EXIT_FAILURE);
  strcpy(*(lines+slot),s);
  slot = ++processed % numlines;
}
有帮助吗?

解决方案

您的例程正在写入超出分配的行缓冲区。

作为参数传递的行的大小(即“len”)可能不包括NUL终止符。当你调用malloc复制行(即“s”)时,你需要为字符串终止符分配一个额外的字节:

 *(lines + slot) = (char *) malloc((len + 1) * sizeof(char));

其他提示

如果您可以使用特定的输入参数一致地重现问题,则应该像这样进行调试:

  • 首先调试到导致问题的精确空闲位置。
  • 然后找出即将释放的内存何时被分配。
  • 接下来,调试到内存分配的位置。
  • 在内存查看器中找到已分配的内存块。请注意块的开头和结尾。可能有一个特殊的值称为 防护块 就在块之前和之后。
  • 现在逐步执行代码,直到内存被释放。在某些时候,您的代码可能会错误地覆盖保护块。 这就是令人反感的言论。

请注意,问题很可能出在程序的完全不同的部分。尽管报告错误的是这个空闲的代码,但覆盖保护块的代码可以在任何地方。

我的第一个问题是你如何计算len?它只是strlen还是包含\ 0终止符的空间?我认为你可能会在你的strcpy中超出你的分配。不良行为往往会出现在单词边界上并且随机出现。另外,请检查以确保源字符串为空终止。如果你在阅读方面犯了错误并且没有终止它们。然后strcpy可能会随机覆盖一些东西。

  *(lines + slot) = (char *) malloc(len * sizeof(char));
  if(*(lines + slot) == NULL) exit(EXIT_FAILURE);
  strcpy(*(lines+slot),s);

也许试试:

  lines[slot] = (char *) malloc((len + 1) * sizeof(char));
  if(lines[slot] == NULL) exit(EXIT_FAILURE);
  if(strlen(s) <= len){
    strcpy(lines[slot],s);
  }
  else{
    /* do something else... */
  }

就一般形式而言,我还鼓励你做一些风格上的改变,使整个事情更具可读性,更容易理解,并且能够抵御错误。

指针算法是有效且有趣的,但我认为如果使用数组形式,你的意图会更清晰:

free(lines[slot]);
lines[slot] = NULL;

而不是

free(*(lines+slot));
*(lines + slot) = NULL;

我也鼓励你使用更少的静力学。在数据结构中通过它们很容易,并将它们传递给您的访问器和更改器。事情发生的地方变得更加清楚,这会妨碍你做以下事情:

static int numlines = 0;
void insert_line(char *s, int len){
    int numlines = 5;

您可以在其中介绍仅对调试感到悲惨的范围问题。

nlines和numlines是否具有相同的值?

在第二个参数中传递长度时,insert_line的调用者是否允许尾随NUL的空间?

我不确定它是否相关,但这两行对我来说似乎很可疑:

  *(lines + slot) = (char *) malloc(len * sizeof(char));
  if((lines + slot) == NULL) exit(EXIT_FAILURE);

首先将malloc的返回值分配给 lines [slot] ,然后检查(lines + slot),如果后者为NULL,则取消引用NULL指针!

如果行[slot](你的*(行+插槽))不为null,当你将malloc()的结果赋给它时,你将泄漏内存。

我假设 lines char * lines []`并且slot在允许的范围内!

我同意雷莫对这两条线的怀疑,但不同意雷莫的切线。我们应该分享信用来发现这个错误。

*(lines + slot) = some value
if((lines + slot) == NULL) then die
should be
if(*(lines + slot) == NULL) then die
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top