【发布时间】:2020-12-30 11:08:24
【问题描述】:
我是 C 新手,这是我在这里的第一篇文章。
我尝试修复此错误以及我遇到的其他错误已使此代码混乱,因此请记住这一点。我的程序从用户那里读取一个复数,并根据命令将其存储或打印到六个 typedefed complex struct {double d1, d2; char *val;} 全局声明的变量之一(A 到 F)。
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.val、B.val等都没有被释放。如果free(input);之前的任何break语句被执行,你将泄漏input指向的内存。 -
但是 A.val 到 F.val 得到 malloc 一次,当我在 readComp 中找到它们时,我首先释放初始化值的选定 var,然后我再次 malloc var,然后将其设置为用户输入作为新输入,从我所看到的它的工作原理以及 GDB 向我展示的内容来看。您可以在上面的示例中看到这一点。有问题的是最后一次免费。
-
发现内存损坏是更大的问题。但请注意,最终的
printf肯定会失败,因为此时input是NULL,并且您尝试对其使用%s格式,这将尝试取消引用NULL指针.只需摆脱第二种格式和参数。 -
发布全局声明变量的定义(A 到 F)。
-
由于很可能问题出在此处未显示的函数内部(例如
readComp()),因此很难提供帮助。我的猜测是,在 readComp() 中,你错误地存储了一个指向输入的指针,然后你释放了输入,之后你释放了一个复数内的指针(它曾经是一个输入指针)。