当我忘记return语句而不是仅仅返回垃圾时,为什么我的C ++程序会崩溃?

时间:2016-09-04 00:08:17

标签: c++ clang llvm freebsd llvm-clang

我最近开始使用CLang来编译嵌入式C ++ ARM程序。

在此之前,我使用GCC和C,几乎专门用于嵌入式工作。

我注意到当我有一个返回值的方法时,我忘记了return语句,程序核心转储。除了我的一个设备驱动程序的“msleep error -1”之外,没有打印错误。这是在FreeBSD上。

我希望忘记return语句只会导致从函数返回垃圾,而不是核心转储。

编辑:我正在返回一个bool,而不是一个指针或对象或任何复杂的东西。即使返回值无关紧要,程序也会崩溃。

发生了什么事?

E.G:

bool MyClass::DummyFunc() {
  <do some stuff and forget the return value>     
}

其他地方:

if(pMyObj->DummyFunc()) {
  print ("Hey, it's true!\n");
} else {
  print ("Darn, it's false!\n");
}

无论返回值如何,该代码都不应该崩溃。

3 个答案:

答案 0 :(得分:4)

从二手资料来源,因为我不想支付C ++标准,它显然说:

  

离开函数末尾相当于没有返回   值;这会导致值返回时出现未定义的行为   功能

这是C ++,当你做一些未定义的事情时,你应该期望它会崩溃你的电脑并吃掉你的洗衣服务,除非实施说明不这样做。

答案 1 :(得分:3)

  

我希望忘记return语句只会导致从函数返回垃圾,而不是核心转储。

     

发生了什么事?

你的期望是错误的,是不是发生了什么。

编译器 - 一个非常复杂的机器 - 可以自由地假设你的函数返回一个值,因为你承诺它会这样做。

然后你违背了这个承诺。

这就是为什么我们不会对实现细节做出假设,特别是在编写行为未定义的程序时。你无法直接比较C ++代码和#34;有些数据会进入这个寄存器,并且有一个这样的调用堆就可以完成这个事情&#34;。

这种方法几乎无限可能会破坏,因为在将C ++代码转换为计算机可读的优化程序的过程中,编译器会进行一系列非常复杂的优化,其中任何一个都可以违反标准规则会被抢购一半。试图准确确定在您的程序的任何特定运行中发生的事情将需要以下知识:

  • CPU品牌,型号和版本
  • 操作系统品牌,型号和版本
  • 编译器品牌,型号和版本
  • 所有编译器标志
  • 10年&#39;使用编译器的源代码
  • 时间机器,用于在程序执行时检查计算机中每一位内存的状态。

这真的不值得。

幸运的是,在某些情况下,我们可以在不背叛抽象的情况下进一步理性化这个案例:例如,考虑当你答应你回复std::string时会发生什么,但是没有,然后,不存在的std::string超出了范围。析构函数是随机废话调用的,并且不会很顺利。

答案 2 :(得分:3)

忘记返回值会导致控制流程到达函数末尾。 C和C ++标准都描述了这种情况。请注意,main是这种情况的一个例外,将单独描述。

  

离开函数末尾相当于没有值的返回;这会导致未定义的行为   在值返回函数C++11 Draft pg 136

我对clang的经验是编译器会处理&#34;未定义行为的实例&#34;因为不会发生并优化掉路径。哪个是合法的,因为行为未定义。通常clang会在省略的路径上发出非法指令,这样如果&#34;不可能的话,代码就会崩溃。发生了,这可能是你的情况。实际上,编译器可以确定调用DummyFunc()会导致未定义的行为,因此不会发生,而是开始优化调用主体。

gcc远远不够友好&#34;并尝试生成一些不错的东西,例如返回0。

请注意,两个编译器都是正确的,并且根据标准生成有效的代码。