【问题标题】:Why is this simple strcat crashing at runtime?为什么这个简单的 strcat 在运行时会崩溃?
【发布时间】:2015-03-08 10:53:31
【问题描述】:

由于某些原因,在多年未使用 C 编程回来后,我无法完成这项工作:

(编译时没有任何抱怨,但它会导致崩溃,当我删除 strcat 行时,可执行文件运行良好)

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv){
    char clibdir[50] = "C:\\Users\\______000\\Desktop\\nodeC\\libraries\\c";
    char varsfile[20] = "\\variables.xml";
    printf("%s\n", clibdir);  //ok
    printf("%s\n", varsfile); //ok
    char *varspath = strcat(clibdir, varsfile);  //this is provoking a crash
    printf("%s\n", clibdir);  //prints right before crash
    printf("%s\n", varspath); //prints right before crash
    return 0;
}

这打印得非常完美,但它使我的 exe 崩溃。这是我的命令行(我正在使用 Visual Studio 2010 中的 cl.exe):

"%vcbin%\vcvars32.bat" && "%vcbin%\cl.exe" /nologo /EHsc main.cpp /link /subsystem:console

【问题讨论】:

  • 它不会导致我崩溃。
  • strcat() 将写入clibdir,它使用字符串文字进行初始化。根据编译器选项,clibdir 可以转换为指向受保护数据段的指针。在该位置写入会导致未定义的行为。
  • @SleuthEye 不,它被声明为char[50],它会放在一个可写的位置,
  • 是的,clibdir 变量大于 50 个字符,导致错误。大小 100 应该没问题。
  • 当您不向我们展示实际崩溃的代码时,您希望我们如何调试您的问题?问题的原始版本显示char clibdir[50] = "\\libraries\\c";,它很短,没有问题。修改后的版本仍然有一个只有 50 个字符长的变量,但它被初始化为 45 个字符,因此再添加 14 个左右的字符会使缓冲区溢出,并且根据崩溃报告,它设法丢弃堆栈 — 这称为 @987654321 @。现在看起来很简单——但这只是因为您向我们展示了实际崩溃的代码!

标签: c string char printf strcat


【解决方案1】:

您的代码崩溃了,因为您没有在clibdir 中分配足够的空间来保存初始字符串和附加字符串,所以您有缓冲区溢出。问题是,您已经从 main() 函数中删除了返回堆栈,因此当您从 main() 程序返回时,程序会出现问题并崩溃。您可能会发现,如果您将return 0; 替换为exit(0);,您的程序将不再崩溃。这是巧合 - 不推荐修复。

故事的寓意是“确保有足够的空间用于添加的字符串”!

明智的解决方法是将clibdir 的大小从 50 增加到至少 60。


...而且...当您提出问题时,请确保您在问题中显示的代码实际上与您在计算机上运行的代码一样崩溃。问题的原始版本有:

char clibdir[50] = "\\libraries\\c";

代替:

char clibdir[50] = "C:\\Users\\______000\\Desktop\\nodeC\\libraries\\c";

没有人能理解为什么代码会崩溃——因为事实上,原始代码不应该崩溃。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-25
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 2022-12-29
    相关资源
    最近更新 更多