【问题标题】:Why do I have a undeclared variable existed? [closed]为什么我有一个未声明的变量存在? [关闭]
【发布时间】:2017-03-18 21:09:08
【问题描述】:

我正在用 C 编写一个函数。我发现当我在 gdb 中调试时,我发现一个指针“result”与声明“result”之前的另一个指针具有相同的地址。我的部分代码:

char* stringSum(char* x, char* y){
    puts(x);
    puts(y);
    printf("\n");

    int lengthx=strlen(x);
    int lengthy=strlen(y);

    int lengths=MIN(lengthx,lengthy);
    int lengthl=MAX(lengthx,lengthy);

    char* s=((lengthx<=lengthy)?x:y);
    char* l=((lengthx>lengthy)?x:y);

    int returnSize=MAX(lengthx, lengthy)+2;//-----I could print result now

    printf("before, short is                          : ");puts(s);

    char* result=malloc(sizeof(char)*returnSize);//-----but result is allocated now

    printf("after allocate memory for result, short is: ");puts(s);//---s is changed!
    result[returnSize-1]='\0';
    ......
}

这个函数得到两个数字的总和(在字符串中),这样我就可以计算两个大数的总和。在 gdb 中:我遇到了这个奇怪的问题:

My problems are in red and yellow rectangles

(在 gdb 中调试时)在 char* result=malloc(sizeof(char)*returnSize); 之前我打印了 s 和结果(所以现在它还没有被声明)并得到了

(gdb) print s
$5 = 0x61f950 "6597242170048699800240000000000"
(gdb) print result
$6 = 0x61f950 "6597242170048699800240000000000"

我无法理解,因为未声明的指针如何指向现有地址? (此函数由另一个具有大量 x 和 y (在字符串中)的函数调用。如果我将它们更改为相对较小的值,我将始终得到正确的答案。此外,如果我创建一个新的 .c 文件并只有这个函数和main函数,再大的值我都不会再有这个问题了。)

我的第二个问题是我打印了两次s,发现第二次打印(声明指针结果后)s变了! (与第一个问题类似,如果我为 x 和 y 选择较小的值或创建一个新的 .c 文件,我不会遇到同样的问题。)

我想我对malloc 有一些问题,但是在网上搜索后我没有找到任何有用的资源可以帮助我解决问题。我有关于内存管理的问题吗?

【问题讨论】:

  • 那段代码是如何编译的?你看过机器/汇编代码吗?代码有什么问题?
  • 当您尝试在定义之前获取result 的值时,我相信结果令人惊讶的是未定义;)。在这种情况下,结果与s相同
  • 但问题似乎是相反的情况也是如此,当分配result 时,s 神奇地改变了......
  • 您是否在抱怨gdb 能够在执行到达其声明之前打印变量?这是正常的。 gdb 不知道变量的声明点。在这种情况下gdb 打印的值将是不可预测的。
  • @n.m.我从来不知道!然后我想我唯一的问题是第二个。非常感谢!

标签: c pointers memory-management malloc declaration


【解决方案1】:

您的代码至少有两个严重问题。

第一个问题是 free 永远不会像 malloc 那样,在每次递归调用时都会造成相当大的内存泄漏。

第二个问题是您尝试分配字符串,这并没有达到您希望的效果。

这是你所做的一个例子(我的 cmets):

 // allocate some memory and assign its address to abcd
 char* abcd=malloc(sizeof(char)*returnSize);

 // throw it away by assigning a different value to abcd
 abcd=karatsuba(stringSum(a,b),stringSum(c,d));
 // then assign yet another different value to abcd
 abcd=stringSubstract(abcd,ac);
 // and another one
 abcd=stringSubstract(abcd,bd);//ab+cd   

 // Code below overflows, because memory abcd is pointing to is 
 // not the original block allocated for it (you threw it away).
 // It is a block allocated and returned by stringSubstract.
 // Its length is not necessarily sufficient to accommodate all
 // the data you are trying to stuff in it.
 int labcd=strlen(abcd);     
 for(i=0;i<=(ns/2-1);i++){
     abcd[labcd+i]='0';
 }
 abcd[lac+i]='\0';

您可以通过在valgrind 下运行程序来验证是否属于这种情况。在s 神秘缩短之前,您将收到指示缓冲区溢出的错误消息。一切都从那里走下坡路。

为了解决此问题,您可能希望使用strcpy 而不是指针分配。另一种解决方法是去掉函数开头的abcd = malloc(...) 行,并使用realloc 确保它们的分配有足够的大小。

此外,您肯定想要修复内存泄漏。完成后,您需要为 malloc 的每个变量调用 free。如果你返回一个malloced 变量,调用者需要在使用它之后释放它。

【讨论】:

  • @非常感谢!我现在使用strcpys 指向的字符串将不再被修改。我对这个问题的问题似乎已经解决了,我知道我的代码中还有其他一些问题。感谢您对valgrind 的建议,因为我以前从未尝试过。我确实在 valgrind 下发现了很多错误。
猜你喜欢
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-15
  • 1970-01-01
  • 2021-01-09
相关资源
最近更新 更多