我確實遇到了這種情況,我在兩個單獨的檔案中宣告了兩個(單獨的)具有相同名稱的全域變數,但沒有使用static,volatile也沒有使用extern它們。一個檔案是 .c,另一個是 .cpp 檔案。
編譯器和構建環境 (GCC) 是 ESP IDF,甚至這些宣告的資料型別也不同。
mqtt_ssl.c:
esp_mqtt_client_handle_t client;
mb_master.cpp:
PL::ModbusClient client(port, PL::ModbusProtocol::rtu, 1);
在運行時,我在重啟 ESP32 時遇到了很多問題,直到我發現,兩個實際上獨立的變數的同名導致了這個問題。
我的猜測是,編譯器對它們都使用了相同的記憶體區域。
我預計,它將作為兩個獨立的物件處理,在記憶體中有自己的區域,這顯然不是真的。在這里
閱讀了一些問題之后,我現在的理解是,如果一個具有相同名稱的變數在沒有宣告的情況下或在兩個單獨的 C/C 檔案中宣告,則行為是未定義的。staticexternvolatile
我花了很長時間才弄清楚這一點。
如果不允許這樣宣告,為什么編譯器/聯結器不拋出錯誤?
GCC 是否可以選擇將這種情況視為錯誤以防止將來出現這種情況?
編輯 1:
這是 xtensa-esp32-elf-gcc.exe (crosstool-NG esp-2021r2-patch3) 8.4.0 的可重現示例。
app_main.c
#include <stdio.h>
void test_sub(void);
uint16_t test1;
void app_main(void)
{
test1 = 1;
printf("app_main:test1=%d\n", test1);
test_sub();
printf("app_main:test1=%d\n", test1);
}
test_sub.c
#include <stdio.h>
int16_t test1;
void test_sub(void)
{
test1 = 2;
printf("test_sub:test1=%d\n", test1);
}
結果:
app_main:test1=1
test_sub:test1=2
app_main:test1=2
test1inapp_main()被 覆寫test_sub(),因為它在兩個檔案中具有相同的名稱。
uj5u.com熱心網友回復:
esp_mqtt_client_handle_t client;是一個暫定的定義。盡管它的名字,它不是一個定義,只是一個宣告,但是如果翻譯單元中沒有常規定義,它會導致在翻譯單元的末尾創建一個定義。
C 標準允許 C 實作選擇它們如何決議多個定義(因為它說它沒有定義行為,所以編譯器和聯結器可以定義它)。在 GCC 版本 10 之前,GCC 中的默認設定是將暫定定義中的定義標記為“通用”,這意味著它們可以與其他定義合并。這導致聯結器不會抱怨這樣的多個定義。
切換-fno-common到 GCC 指示它不要這樣做;定義不會被標記為“通用”,如果看到多個定義,聯結器會報錯。
uj5u.com熱心網友回復:
你的問題真的是變數被隱藏了嗎?通常對于全域變數,問題可能是變數沒有按正確的順序初始化。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/532242.html
標籤:C C海合会范围全局变量
