使用gdb--仍然找不到malloc错误

Using gdb--still can't find malloc error

我已经查看了之前的 posts,但它们没有帮助我找到我的问题...为了简短起见,我正在制作一个函数,应该逐行读取文本文件(是的,我知道有很多这样的 post)。但是当我通过 CMD 运行 我的程序时,它给了我这个错误:

Program received signal SIGSEGV, Segmentation fault.
__GI___libc_realloc (oldmem=0x10011, bytes=1) at malloc.c:2999
2999    malloc.c: No such file or directory.

漂亮确定我正确地写出了我的malloc/realloc行。我已经尝试找到很多与此类似的 post,但所提供的解决方案中有 none 有帮助。如果您有任何我错过的 post 建议,请告诉我。无论如何,这是我的功能:

char* read_single_line(FILE* fp){
  char* line = NULL;
  int num_chars = 0;
  char c;
  fscanf(fp, "%c", &c);
  while(!feof(fp)) {
    num_chars++;
    line = (char*) realloc(line, num_chars * sizeof(char));
    line[num_chars -1] = c;
    if (c == '\n') {
      break;
    }
    fscanf(fp, "%c", &c);
  }
  if(line != NULL) {
    line = realloc(line, (num_chars+1) * sizeof(char));
    line[num_chars] = '[=11=]';
  }
  return line;
}


void read_lines(FILE* fp, char*** lines, int* num_lines) {
  int i = 0;
  int num_lines_in_file = 0;
  char line[1000];
  if (fp == NULL) {
    *lines = NULL;
    *num_lines = 0;
  } else {
    (*lines) = (char**)malloc(1 * sizeof(char*));
    while (read_single_line(fp) != NULL) {
      (*lines)[i] = (char*)realloc((*lines)[i], sizeof(char));
      num_lines_in_file++;
      i++;
    }
    *lines[i] = line;
    *num_lines = num_lines_in_file;

  }
}

非常感谢任何帮助——我是 C 语言的初学者,请听我说完!!

char line[1000];
:
while (read_single_line(fp) != NULL) {
:
}
*lines[i] = line;

这对我来说一点都不合适。你的 read_single_line 函数 return 是一个实际的行,但是除了根据 NULL 检查它之外,你实际上从未 存储 它在任何地方。相反,您将行指针指向 line,一个自动作用域的变量,它实际上可以包含任何内容(更令人担忧的是,可能没有终止符)。

我认为您可能应该存储 read_single_line 中的 return 值并使用它来设置行指针。


顺便说一句,一次扩展一个字符的缓冲区也可能效率很低。我建议最初分配更多字节,然后保留该容量和当前正在使用的字节。然后,只有当你即将使用超出你的能力时,你才会扩展,并且扩展不止一个。在伪代码中,类似于:

def getLine:
    # Initial allocation with error check.

    capacity = 64
    inUse = 0
    buffer = allocate(capacity)
    if buffer == null:
        return null

    # Process each character made available somehow.

    while ch = getNextChar:
        # Expand buffer if needed, always have room for terminator.

        if inUse + 1 == capacity:
            capacity += 64
            newBuff = realloc buffer with capacity

            # Failure means we have to release old buffer.

            if newBuff == null:
                free buffer
                return null

        # Store character in buffer, we have enough room.

        buffer[inUse++] = ch

    # Store terminator, we'll always have room.

    buffer[inUse] = '[=11=]';
    return buffer

您会注意到,除了更有效的重新分配之外,对所述分配的错误检查也更好。

while (read_single_line(fp) != NULL) {
      (*lines)[i] = (char*)realloc((*lines)[i], sizeof(char));
      num_lines_in_file++;
      i++;
    }
    *lines[i] = line;

这个短片段中的错误多于行。让我们一一回顾。

 while (read_single_line(fp) != NULL) 

你读了一行,检查它是否是一个空指针,然后把它扔掉,而不是把它留在周围,把它累积在 lines 数组中。

   (*lines)[i] = (char*)realloc((*lines)[i], sizeof(char));

您正在尝试重新分配 (*lines[i])。首先,它不存在于 i==0 之外,因为 (*lines) 只被分配来包含一个元素。其次,重新分配单独的行是没有意义的,因为您正在(应该)从行读取功能中获得完美的现成行。你想重新分配 *lines 而不是:

*lines = realloc (*lines, i * sizeof(char*));

现在这两行

  num_lines_in_file++;
  i++;

本身不是错误,但为什么有两个变量总是具有完全相同的值?此外,您希望它们(它)位于 realloc 行之前,按照通常的 increment-realloc-assign 模式(您在其他函数中使用它)。

说到分配部分,没有。您现在应该插入一个:

(*lines)[i-1] = // what? 

你在调用read_single_line时应该保存的行指针,就是这样。从头开始:

char* cur_line;
int i = 0;
*lines = NULL;
while ((cur_line=read_single_line(fp)) != NULL) 
{
   ++i;
   *lines = realloc (*lines, i * sizeof(char*));
   (*lines)[i-1] = cur_line;
}
*num_lines = i;

最后一个

   *lines[i] = line;

简直丑爆了。

首先,lines不是一个数组,它是一个指向单个变量的指针,所以lines[i]访问星际尘埃。其次,您正试图为其分配一个局部变量的地址,一旦您的函数 returns,该变量将不复存在。第三,它在循环外做了什么?如果你想用空指针终止你的线数组,这样做:

} 
*num_lines = i;
++i;
*lines = realloc (*lines, i * sizeof(char*));
(*lines)[i-1] = NULL;

但考虑到您 return 的行数,这可能没有必要。

免责声明:none 以上内容已经过测试。如果有任何错误,请修复它们!