[英]Difference between gcc5 and gcc8 with respect to return values of a function
[英]Why declaring a return value for a function that doesn't return nothing leads to run-time crash in gcc8 only
在下面的代碼中,將一個函數聲明/定義為int setYear(int year_h){year = year_h;}
(而不是void setYear(...)
,這導致gcc 8中的運行時崩潰,並帶有標志-O[X]
。
具體問題:
main.cpp中:
#include <iostream>
using namespace std;
int year = 2000;
int setYear(int year_h){year = year_h;}
int main()
{
cout << "Hello World!" << endl;
setYear(2019);
cout << "Year: " << year << endl;
return 0;
}
運行時崩潰:
g++-8 -O2 -o main main.cpp
./main
Hello World!
Hello World!
Segmentation fault (core dumped)
適用於:
g++-7 -O2 -o main main.cpp
要么
g++-8 -o main main.cpp
編輯: C ++中的省略省略語句的問題回答了我的第二個問題,但沒有回答第一個問題(關於gcc 7和gcc 8的區別)。
從GCC 8開始,當使用-Og
編譯源代碼時, setYear
函數根本沒有RET
指令(在更高級別上,該函數被內聯,這使得了解正在發生的事情更加困難),並且該函數的main
調用位置也缺乏任何延續。
在Compiler Explorer中查看原始代碼以進行比較:
<...>
setYear(int):
mov DWORD PTR year[rip], edi
.LC0:
.string "Hello World!"
main:
<...>
並且返回類型int
的代碼已更改為void
( link ):
<...>
setYear(int):
mov DWORD PTR year[rip], edi
ret
.LC0:
.string "Hello World!"
.LC1:
.string "Year: "
main:
<...>
僅此一個遺漏就足以使執行流突入main
(在另一節中聲明了.string
),再次執行它而不是返回到調用點。 顯然,當函數中除了main
返回non- void
之外沒有return
語句時,gcc認為不值得添加RET
指令。
當然,在許多情況下,編譯器可以在編譯階段輕松檢測到該問題。 我建議使用-Werror=return-type
選項,該選項無條件地使其成為錯誤(與-Werror
通常不同)。 當您要避免使用此選項時,這種情況非常罕見,它非常有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.