9

我正在为一项任务实施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;
}
4

6 回答 6

7

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

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

 *(lines + slot) = (char *) malloc((len + 1) * sizeof(char));
于 2008-10-24T13:30:43.460 回答
4

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

  • 首先调试到导致问题的精确释放。
  • 然后找出即将被释放的内存何时被malloc'ed。
  • 接下来,调试到内存被malloc'ed的地方。
  • 在内存查看器中找到分配的内存块。注意块的开始和结束。在块之前和之后可能有一个称为保护块的特殊值。
  • 现在单步执行代码,直到内存被释放。在某些时候,您的代码应该错误地覆盖保护块。那是冒犯性的陈述。

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

于 2008-10-24T07:32:39.793 回答
1

我的第一个问题是你如何计算 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;

您可以在其中引入难以调试的范围界定问题。

于 2008-10-24T12:58:45.007 回答
0

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

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

于 2008-10-24T07:11:10.417 回答
0

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

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

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

此外,如果 lines[slot] (你的 *(lines+slot)) 不为空,当你将 malloc() 的结果分配给它时,你会泄漏内存。

我假设lineschar*lines[]` 并且插槽在允许的边界内!

于 2008-10-24T07:18:08.980 回答
0

我同意 remo 对这两行的怀疑,但不同意 remo 的切线。我们应该分享发现这个错误的功劳。

*(lines + slot) = some value
if((lines + slot) == NULL) then die
should be
if(*(lines + slot) == NULL) then die
于 2008-10-24T07:23:48.627 回答