当返回值丢失时,C++ 代码行为异常
c++ code behaves abnormally when the return value is missing
GCC 9.2.1 给出了一个警告,指出"函数中没有返回语句返回非 void",但是,代码确实可以编译(我用标志 -O3 和 -finline-functions 编译(。
我希望程序没有输出,因为 while 循环的条件计算结果应为 false。但是,我从程序中获得了以下输出(打印在 while 循环中(:
"it != mMap.end((: 0">
输出特别奇怪,因为打印的值(即 0 或"false"(也是 while 循环的条件。
打印后,程序出现段错误,因为迭代器变得无效(通过 while 循环中的it++
,而这不应该执行(。
我想这一切都可以归结为缺少的返回值。但是,我发现令人惊讶的是,代码的行为如此病态,仅仅是因为没有提供返回值。我希望
能深入了解正在发生的事情。#include <iostream>
#include <tr1/unordered_map>
struct Test
{
int Dummy (void) const
{
std::tr1::unordered_map<int, int>::const_iterator it = mMap.begin();
while (it != mMap.end())
{
std::cout << "it != mMap.end(): " << (it != mMap.end()) << std::endl;
it++;
}
}
std::tr1::unordered_map<int, int> mMap;
};
int main (void)
{
Test test;
test.Dummy();
return 0;
}
从非void
函数返回而不提供返回值是欠精细的行为,因此编译器可以做任何它想做的事情。
编译器在这种情况下所做的特别是,它发现跳过循环会触发 UB,因此假设循环至少进入一次。因此,它假设它可以安全地进入循环而无需检查条件,因为编译器相信程序的作者没有调用任何未定义的行为。
这当然是我的猜测。
您应该使用-Wextra
打开警告,并在gcc
中-Wall
,例如启用警告Control reaches the end of a non-void function
,这样您就不会忘记修复这样的东西。要强制执行它,请启用编译器标志-Werror
。
不返回值会调用未定义的行为,因此如果函数返回,编译器可以返回垃圾值或使程序崩溃(这是clang
通常所做的(。这很糟糕,你永远不应该像那样保留损坏的代码。为了获得更多见解,您可以使用反汇编器并查看编译器在函数结束时做了什么。
- 我在c++代码中生成了一个运行时#3异常
- 孤立代码块在结构中引发异常
- 是否值得降低我的代码的可读性,以便在出现内存不足错误时提供异常安全性?
- VisualStudios 会抛出异常,而代码块不会 [C++]
- [longjmp/setjmp]c++ 相同的代码窗口有异常 Linux 没有错误并且运行良好
- 为什么代码段会引发浮点异常?
- 我应该C++自定义异常代码放在哪里?
- 添加新行时工作代码引发异常.调试技巧?
- 当返回值丢失时,C++ 代码行为异常
- 尝试在 QT 项目中调用 Java 代码时未找到类异常
- 为什么此代码导致未处理的异常失败
- 调用参数不是原子参数的函数是此代码引发异常的原因吗?
- 无法看到引发异常的代码行
- 使用双LL在C++中实现Stack失败,出现异常"EXC_BAD_ACCESS(代码=2,地址=0x7fff5
- CPP代码中出现FileNotFound异常
- 当没有浮点数据类型时,为什么此代码会出现浮点异常
- 是否正确处理了此代码异常?
- STL 中是否有任何错误代码异常
- 关于代码异常的一个问题
- Arduino 代码异常 - LCD 出现故障并显示多个 'if' 语句