簡體   English   中英

為什么聲明不返回任何內容的函數的返回值只會導致gcc8中的運行時崩潰

[英]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]

具體問題:

  1. 在gcc 7中,gcc 8發生了什么變化?
  2. 我可以使用哪些標志(如果有的話)在gcc8中生成編譯錯誤(而不是警告)?

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的代碼已更改為voidlink ):

<...>
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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM