c++ - 为什么在没有返回变量的情况下调用 MessageBox[etc]() 会导致程序崩溃?

标签 c++ winapi messagebox access-violation crash

因此,如果我编写以下代码:

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 错误。了解可能的原因将帮助我查明错误,因为项目代码太大而无法发布(无论如何我都需要我 friend 的许可才能发布他的代码)。

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

编辑:

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

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

最佳答案

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

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

char dummy[52];
some_function();

值得庆幸的是,有一个较长的评论解释说删除虚拟对象会导致 some_function 崩溃。它位于一个非常古老的应用程序中,因此没有人敢碰它,并且 some_function 是我们无法控制的完全不同的模块。哦,是的,该应用程序在炼油厂或核电站等工业设施中顺利运行了 20 多年...^_^

关于c++ - 为什么在没有返回变量的情况下调用 MessageBox[etc]() 会导致程序崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15763120/

相关文章:

c++ - 段错误(核心转储)只有更大的输入

C++ |生成10-20之间的伪数

c++ - 需要多平台存档库

c - 为什么我无法获取目录名称

c++ - 如何检测 Windows 是否正在关闭或重新启动

c# - MessageBoxButtons 的语言与当前文化的语言不同

c# - CustomMessageBox 中的列表框总是向上滚动

c++ - 堆栈上的匿名对象,在 C++ 中?

c++ - 在计时器执行过程中使用 c++ KillTimer() 是否安全?

c# - 在没有用户输入的情况下以编程方式拆卸 MessageBox