【问题标题】:Why would calling MessageBox[etc]() without a return variable cause the program to crash?为什么在没有返回变量的情况下调用 MessageBox[etc]() 会导致程序崩溃?
【发布时间】:2013-04-02 11:36:52
【问题描述】:

所以如果我写下面的代码:

MessageBoxA(0, "Yo, wazzup!", "A Greeting From Earth", 0);

程序在退出时因访问冲突而崩溃。当我这样写代码时:

int a;
a = MessageBoxA(0, "Yo, wazzup!", "A Greeting From Earth", 0);

它不会崩溃。现在我知道它为什么会崩溃它崩溃了,这要归功于我问的另一个问题,也是关于参数不匹配的问题,但我不知道为什么它会崩溃。

那么为什么这会导致 APPCRASH? 我一直认为调用具有返回类型的函数而不实际给出返回类型是安全的,例如:

int SomeFunction (void) {
   std::cout << "Hello ya'll!\n";
   return 42;
}

int main (void) {
   int a;

   // "Correct" ?
   a = SomeFunction();
   a = MessageBoxA(0, "Yo, wazzup!", "A Greeting From Earth", 0);

   // "Incorrect" ?
   SomeFunction();
   MessageBoxA(0, "Yo, wazzup!", "A Greeting From Earth", 0);

}

当我运行这种“干净”测试(在新文件中)时,我没有收到任何错误。 在我的程序中运行时,它似乎只给出了 MessageBox/MessageBoxA 的错误。了解可能的原因将有助于我查明错误,因为项目代码太大而无法发布(无论如何我都需要我朋友的许可才能发布他的代码)。

其他信息:
编译器 = GCC
平台 = Windows

编辑:

更新
到目前为止,感谢大家的反馈。所以我决定通过调试器运行它...现在 Code::Blocks 不会调试项目,除非它是从项目文件 (*.cbp) 加载的 - AFAIK。所以我创建了一个实际项目并将我们项目的主文件复制粘贴到项目中。然后我在调试模式下运行,并没有收到警告。然后我在构建模式下编译,它运行良好。
接下来,我决定在 Dev-C++ 中打开一个新文件并通过调试运行它,然后是最终构建过程,我再次没有遇到任何构建或调试错误.我无法在 Dev-C++ 中重现此错误,即使使用我们的主文件(如在 Code::Blocks 中导致错误的那个)。

结论
问题一定出在Code::Blocks。 AFAIK,他们都使用 GCC,所以我很困惑。我唯一能想到的是版本差异或者我的编译器设置或同样模糊的东西。优化器设置或任何其他编译器设置会以某种方式导致这种错误吗?

【问题讨论】:

  • 只是不应该崩溃,你还有另一个问题。请在调试器中运行您的程序,它将帮助您查明崩溃。
  • 除非你能给出具体的重现,否则它永远不会发生
  • 它可能是堆栈损坏...它的可重复性如何?
  • 尝试在应用程序验证程序下运行您的应用程序,它通常会更早地捕获损坏错误

标签: c++ winapi messagebox access-violation crash


【解决方案1】:

具有返回值的版本不会崩溃,因为它在堆栈上多了一个 int。您的错误代码读取了堆栈的边界,然后遇到访问冲突。但是如果你有更多的堆栈,你将不会点击保护页面,因为这只是足够的额外堆栈。如果错误代码只读取它是可以的,但仍然损坏。

我们有一段 WTF 诱导代码,如下所示:

char dummy[52];
some_function();

谢天谢地,有一条长长的评论解释说删除 dummy 会导致 some_function 崩溃。它在一个非常古老的应用程序中,所以没有人敢碰它,some_function 是完全不同的模块,我们无法控制。哦,是的,该应用程序在工业设施(如炼油厂或核电站)的现场平稳运行了 20 多年...... ^_^

【讨论】:

猜你喜欢
  • 2023-02-23
  • 1970-01-01
  • 2019-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多