【问题标题】:Getting double free or corruption !prev in C在 C 中获得双重释放或损坏!prev
【发布时间】:2020-12-30 11:08:24
【问题描述】:

我是 C 新手,这是我在这里的第一篇文章。

我尝试修复此错误以及我遇到的其他错误已使此代码混乱,因此请记住这一点。我的程序从用户那里读取一个复数,并根据命令将其存储或打印到六个 typedefed complex struct {double d1, d2; char *val;} 全局声明的变量之一(AF)。

GDB 将我带到底部的 free 并且从我所看到的情况来看,它有时会释放输入,有时它不会,出于某种奇怪的原因,它还取决于我选择的 var,如下面的示例所示。请注意,remove_space_tab 属于 void 类型,并从返回的地址 malloc 修改原始用户输入。这可能是一个愚蠢的初学者的错误,我猜是记忆的问题。

:
read_comp A, 2.56, -1.32

0x908f068   read_compA,2.56,-1.32

0x908f008   0.00+0.00i // this 4 lines are from printf's that extend to readComp function

0x908f008  // 

0x908f008  //

0x908f008   2.56+(-1.32)i //

0x908f068   read_compA,2.56,-1.32

(nil)   (null)

Enter a command:
read_comp F, 5.61, -7.56

0x908f068   read_compF,5.61,-7.56

0x908f058   0.00+0.00i //

0x908f058 //

0x908f058 //

0x908f058   5.61+(-7.56)i // F does free the initialised val and sets the user input as the new val

0x908f068   read_compF,5.61,-7.56 // doesn't free this 
*** glibc detected *** ./mycomp: double free or corruption (!prev):
0x0908f068

int main() {

  A.d1 = 0;
  A.d2 = 0;
  B.d1 = 0;
  B.d2 = 0;
  C.d1 = 0;
  C.d2 = 0;
  D.d1 = 0;
  D.d2 = 0;
  E.d1 = 0;
  E.d2 = 0;
  F.d1 = 0;
  F.d2 = 0;

  A.val = (char*) malloc(12 * sizeof(char));
  B.val = (char*) malloc(12 * sizeof(char));
  C.val = (char*) malloc(12 * sizeof(char));
  D.val = (char*) malloc(12 * sizeof(char));
  E.val = (char*) malloc(12 * sizeof(char));
  F.val = (char*) malloc(12 * sizeof(char));

  sprintf(A.val, "%.2lf+%.2lfi", A.d1, A.d2);
  sprintf(B.val, "%.2lf+%.2lfi", B.d1, B.d2);
  sprintf(C.val, "%.2lf+%.2lfi", C.d1, C.d2);
  sprintf(D.val, "%.2lf+%.2lfi", D.d1, D.d2);
  sprintf(E.val, "%.2lf+%.2lfi", E.d1, E.d2);
  sprintf(F.val, "%.2lf+%.2lfi", F.d1, F.d2);

  while (1) {
    input = malloc(30 * sizeof(char));
    printf("\nEnter a command:\n");
    gets(input);
    remove_space_tab(input);
    printf("\n%p   %s\n", input, input);

    if (strncmp(input, "stop", 4) == 0 && *(input + 4) == '\0') {
      break;
    } else if (strncmp(input, "stop", 4) == 0 && *(input + 4) != '\0') {
      printf("Extraneous text after end of command.");
      break;
    }
    if (strncmp(input, "read_comp", 9) == 0) {
      input += 9;
      readComp(input);
      input -= 9;
    }

    if (strncmp(input, "print_comp", 10) == 0) {
      if (!('A' <= *(input + 10) && 'F' >= *(input + 10))) {
        printf("\nUndefined complex variable.\n");
        break;
      }
      if (*(input + 11) != '\0') {
        printf("\nExtraneous text after end of command.\n");
        break;
      }
      printComp(input[10]);
    }

    printf("\n%p   %s\n", input, input);
    free(input);
    input = NULL;
    if (input != NULL) {
      printf("Memory could not be allocated.");
      break;
    }
    printf("\n%p   %s\n", input, input);

  }

  return 0;
}

【问题讨论】:

  • 这里肯定有未释放的内存。 A.valB.val 等都没有被释放。如果free(input);之前的任何break语句被执行,你将泄漏input指向的内存。
  • 但是 A.val 到 F.val 得到 malloc 一次,当我在 readComp 中找到它们时,我首先释放初始化值的选定 var,然后我再次 malloc var,然后将其设置为用户输入作为新输入,从我所看到的它的工作原理以及 GDB 向我展示的内容来看。您可以在上面的示例中看到这一点。有问题的是最后一次免费。
  • 发现内存损坏是更大的问题。但请注意,最终的printf 肯定会失败,因为此时inputNULL,并且您尝试对其使用%s 格式,这将尝试取消引用NULL 指针.只需摆脱第二种格式和参数。
  • 发布全局声明变量的定义(A 到 F)。
  • 由于很可能问题出在此处未显示的函数内部(例如readComp()),因此很难提供帮助。我的猜测是,在 readComp() 中,你错误地存储了一个指向输入的指针,然后你释放了输入,之后你释放了一个复数内的指针(它曾经是一个输入指针)。

标签: c malloc free


【解决方案1】:

至少这个问题。

在最后一行,input == NULL 和使用 "%s" 是未定义的行为 (UB)。

// printf("\n%p   %s\n", input, input);
printf("\n%p\n", input);

【讨论】:

  • 那么为什么在示例中当 var 为 A 时它可以工作并打印 nil 和 null?即使我删除它,它仍然会打印错误。
  • 如果有帮助,它还会打印 Program received signal SIGABRT, aborted some address in __kernel_vsyscall ()。
  • Undefined, unspecified and implementation-defined behavior。 UB 被调用后发生的事情只是Undefined。它可以做任何事情,从看起来正常工作到 SegFault 或介于两者之间的任何事情。进一步malloc(12) 是所需要的。不需要强制返回,sizeof(char) 定义为1
  • 大卫 C 排名。但是我仍然不明白为什么 C 有时会释放内存,有时又不想释放我分配给输入的内存,而且 free 和 malloc 都在 main 内部的一个循环中,并且在我的其他任何地方都没有提到程序。正如我之前所说,给我输入的指针与 free 中的指针相同(通过打印地址检查) 不知道,C 中的语法是如此复杂。我很难抓住它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-13
  • 2010-10-27
  • 2012-05-20
  • 1970-01-01
相关资源
最近更新 更多