簡體   English   中英

阻止GCC優化全局變量的問題

[英]Issue preventing GCC from optimizing out global variable

我正在使用ARM-GCC v4.9(2015-06-23發布)用於STM32F105RC處理器。
我搜索了stackoverflow.com,我發現這是為了試圖說服gcc 不要優化全局變量,如下所示:

static const char AppVersion[] __attribute__((used)) = "v3.05/10.oct.2015";

然而, 令我驚訝的是 ,編譯器優化了AppVersion變量!
順便說一句:我正在使用優化級別-O0 (默認)。
我也嘗試使用volatile關鍵字(如其他線程所示),但它也不起作用:(
我已經嘗試過(void)AppVersion; 但它不起作用......
智能編譯器!? 我覺得太聰明了......

在此期間,我使用printf(AppVersion); 在我的代碼中的一些地方,只是為了能夠保持版本......但這是一個粗野的解決方案:(
所以,問題是:是否有其他技巧可以完成這項工作,即保持版本不被GCC優化掉?

[編輯]:
我也試過這樣(即沒有static ):

const char AppVersion[] __attribute__((used)) = "v3.05/10.oct.2015";

......它也不起作用:(

鑒於存在“靜態”,所有聲明都要求編譯器在文件中的某個任意位置以某種順序包含表示字符串“v3.05 / 10.oct.2015”字符的字節,但不要打擾告訴任何人把它們放在哪里。 鑒於編譯器可以合法地在代碼圖像文件中的某處寫入該字節序列, 無論它是否出現在代碼中的任何地方,這樣的聲明實際上並不是非常有用。 可以肯定的是,這樣的序列不可能完全偶然地出現在代碼中,因此掃描二進制圖像可能是一種可靠的方法來確定它出現在代碼中,但總的來說它更好一些有一些肯定地確定可以找到字符串的方法。

如果字符串未聲明為static,則需要編譯器告訴鏈接器它在哪里。 由於鏈接器通常輸出各種位置的所有符號的名稱和地址,包括符號表,調試信息文件等,它們可以以鏈接器一無所知的各種方式使用,它可能能夠分辨代碼中沒有使用符號,但通常不知道某個其他實用程序是否可能期望在符號表中找到它並使用它。 一個說明符號被“使用”的指令將告訴鏈接器即使它不知道任何對該符號感興趣的東西,但是在更大的宇宙中,鏈接器一無所知對它感興趣。

每個編譯單元通常會向鏈接器提供一些信息並說“這是一些東西;我需要一個符號來開始它,但我可以從中計算所有內部的所有地址”。 鏈接器無法知道這些blob的哪些部分實際被使用,所以它別無選擇,只能逐字接受整個事物。 如果編譯器在其blob中包含未使用的靜態聲明,則它們會將其傳遞給輸出文件。 另一方面,編譯器知道如果它沒有為該blob中的某些東西導出符號,那么下游的任何其他人都無法找到它,無論該對象是否被包含在內; 因此,能夠包括這樣的blob通常沒什么好處,並且編譯器編寫者通常必須推理提供強制這種包含的特征。

不幸的是,我不知道這樣做的實用工具。
然而,有另一種解決方案。 將AppVersion更改為:

static char * AppVersion = "v3.05/10.oct.2015";

並添加:

__asm__ ("" : : "" (AppVersion));

到你的主要功能。

您看到我刪除了'used'屬性,根據文檔這是一個函數屬性。

其他解決方案: gcc是否有任何選項可以在ELF二進制文件中添加版本信息?

雖然我覺得這個最容易。 這基本上不會讓編譯器和鏈接器刪除AppVersion,因為我們告訴它這段內聯匯編使用它,即使我們實際上沒有插入任何內聯匯編。

希望這對您來說是令人滿意的。

作者: Andre Simoes Dias Vieira
原始鏈接https//answers.launchpad.net/gcc-arm-embedded/+question/280104

似乎使用自定義部分也有效。

代替

__attribute__((used))

嘗試

__attribute__((section(".your.section.name.here")))

鏈接器不會觸及它, strip命令也不會觸及它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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