代码之家  ›  专栏  ›  技术社区  ›  mav

C++程序中非常奇怪的堆栈溢出

  •  2
  • mav  · 技术社区  · 16 年前

    不久前我编写了一个程序(Mac OS X,C++,SDL,FMOD),它的性能相当不错。但最近我想扩展它的功能,并添加了更多的代码。现在,当我运行它并尝试测试新功能时,程序会与SIGABRT崩溃。

    查看调试器,在函数堆栈上我看到:

    • _杀死
    • 提升
    • __中止
    • __堆栈检查失败
    • odtworz<--我的功能被修改了

    ...
    
    koniec = 0;
    while ( koniec == 0 ) {
        ...
        if (mode == 1) {
            ...
        }
        else if (mode == 2) {
            ...
        }
        else if (mode == 3) {
           piesniOrkiestrowe[0] = '\0'; 
           while ( piesniOrkiestrowe[0] == '\0' ) { 
               losowaPiesn(); 
               char * piesnOrkiestrowa = szukajPiesniOrkiestrowej(); 
               if ( piesnOrkiestrowa != NULL ) 
                  strcpy(piesniOrkiestrowe, piesnOrkiestrowa); 
           } 
           char nowyPiesnPlik[25]; 
           sprintf(nowyPiesnPlik, "%sorch/%s", PIESNI_DIR.c_str(), piesniOrkiestrowe);
        }
    }
    

    现在,我不想删除这个代码,因为它是为我的程序的其他模式。它在那里工作得很好。有什么线索我可以查到吗?这可能有什么问题?

    4 回复  |  直到 13 年前
        1
  •  16
  •   Hans Passant    16 年前

    它是


    使用注释中的代码更新问题之后:strcpy和sprintf调用都是堆栈损坏的最佳候选。我在最初的回答中提到的缓冲区溢出问题。猜猜看:现在的NPLIK看起来 非常 小的。函数的作用是:将过多的字符写入缓冲区,并覆盖“canary”。当金丝雀被踩在地上时,运行库将鸣笛(fowl:)

        2
  •  2
  •   eeerahul Stalin Pimentel    14 年前

    我经历了一个非常类似的问题,代码崩溃 __stack_chk_fail 在我的情况下,上述建议的解决方案是摆脱 sprintf() .

        3
  •  0
  •   mav    16 年前

    找到了!

    在我给出代码之前,culrpit就已经出现了,但是Hans Passant给了我一个线索,告诉我应该看什么。它看起来像这样:

    char piesnPlik[25];
    if ( mode == TRYB_PIANINO )
        sprintf(piesnPlik, "%spiano/%s.mp3", PIESNI_DIR.c_str(), wybranaPiesn);
    else if ( tryb == TRYB_ORKIESTRA )
        sprintf(piesnPlik, "%sorch/%s", PIESNI_DIR.c_str(), piesniOrkiestrowe);
    else if ( tryb == TRYB_NAGRANIE )
        sprintf(piesnPlik, "%s/%s", NAGRANIA_DIR.c_str(), nazwaNagraniaMP3);
    

    所以,我今天添加了第三个if哪个用户“piesnPlik”变量。但是“nazwaNagraniaMP3”比复制到那里的另外两个变量长,所以它破坏了堆栈。但令人难以置信的是,它成功地与所有SDL的东西之后,只有崩溃后,从功能返回。

        4
  •  0
  •   John    16 年前

    一点也不奇怪。当涉及到堆栈溢出或堆损坏时,您应该预料到奇怪的情况。堆栈指针、程序计数器或其他程序状态已损坏,因此调试器或跟踪工具无法准确报告崩溃时程序所在的位置。这个bug可能在代码的其他地方,远离您发布的代码片段。从最近修改的代码开始。

    正如您发现的那样,您自己已经编写了一个很好的堆栈损坏示例。无论如何,这里有一个:

    void foo (){ 
        int x[0];
        x[-99] = -1;
    }
    
    推荐文章