當使用未初始化的指標在系統中寫入記憶體(在 C 中)時,程式員可以做什么來檢測和/或糾正所產生的問題,例如在運行時:
int main()
{
int *ptr1;
*ptr1 = 100;
}
uj5u.com熱心網友回復:
任何最近的、體面的編譯器都會使用正確的標志警告此類代碼。這里的一般建議是始終啟用所有警告。使用-Wall對于g /鐺,和/W4上MSVC(的Visual C )。
例如:
uninit.cpp:
int main()
{
int *ptr1;
*ptr1 = 100;
}
克 :
$ g -Wall uninit.cpp
uninit.cpp: In function ‘int main()’:
uninit.cpp:4:11: warning: ‘ptr1’ is used uninitialized in this function [-Wuninitialized]
4 | *ptr1 = 100;
| ~~~~~~^~~~~
叮當 :
$ clang -Wall uninit.cpp
uninit.cpp:4:6: warning: variable 'ptr1' is uninitialized when used here [-Wuninitialized]
*ptr1 = 100;
^~~~
uninit.cpp:3:14: note: initialize the variable 'ptr1' to silence this warning
int *ptr1;
^
= nullptr
1 warning generated.
如您所見,編譯器甚至會提示您需要使用的標志來專門僅打開此單個警告 ( -Wuninitialized)。
即使打開了警告,也會生成一個可執行檔案。如果您希望編譯在遇到警告時失敗,請添加-Werror:
g -Wall -Werror uninit.cpp
uninit.cpp: In function ‘int main()’:
uninit.cpp:4:11: error: ‘ptr1’ is used uninitialized in this function [-Werror=uninitialized]
4 | *ptr1 = 100;
| ~~~~~~^~~~~
cc1plus: all warnings being treated as errors
您再次看到編譯器為您指出必須添加什么標志才能僅將這一特定警告轉換為錯誤 ( -Werror=uninitialized)。
要對潛在的無效記憶體訪問進行更廣泛的處理,您可以使用地址清理器:
g -fsanitize=address,undefined -g uninit.cpp
運行程式時的輸出:
$ ./a.out
uninit.cpp:4:11: runtime error: store to null pointer of type 'int'
AddressSanitizer:DEADLYSIGNAL
=================================================================
==191==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x562eab7b9255 bp 0x7ffc74f9a750 sp 0x7ffc74f9a740 T0)
==191==The signal is caused by a WRITE memory access.
==191==Hint: address points to the zero page.
#0 0x562eab7b9254 in main /home/someuser/uninit.cpp:4
#1 0x7ff1e1d6e0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6 0x270b2)
#2 0x562eab7b912d in _start (/home/someuser/a.out 0x112d)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/someuser/uninit.cpp:4 in main
==191==ABORTING
這會增加額外的檢查,因此會帶來性能成本;但它會在運行時警告您/停止程式時,當發生更復雜的問題導致的訪問問題時
至于糾正此類錯誤,它取決于正確解決方案的背景關系 - 沒有適合每個用例的單一答案,除了通用確保在第一次使用之前初始化指標。一個好的規則是總是在宣告之后直接初始化指標。這當然只會處理如上所示的簡單問題,而不是有條件地將指標設定為某個無效值的問題。使用一般的錯誤修復技術來解決這些問題;)
一般建議通常還包括盡可能避免使用原始指標。
uj5u.com熱心網友回復:
clang 和 GCC 都支持 sanitizers 來捕獲此類錯誤。例如:
int main()
{
volatile int* p; // volatile so it's not removed at compile time
*p = 0;
}
編譯并運行它:
$ g main.cpp -O3 -fsanitize=undefined
$ ./a.out
main.cpp:5:8: runtime error: store to null pointer of type 'volatile int'
如您所見,有一條明確的錯誤訊息,其中包含確切的代碼位置。
uj5u.com熱心網友回復:
當使用未初始化的指標時,程式員可以做些什么來糾正所產生的問題
程式員可以更改程式,以便在程式中不使用不確定的值。您可以像這樣修復示例程式:
int main()
{
}
程式員可以做什么來檢測......何時使用了未初始化的指標
程式員可以讀取源代碼,并推斷何時使用了不確定的值。
如果程式員幸運的話,程式員可以閱讀他們的程式在編譯時可能產生的警告。在示例程式的情況下:
warning: variable 'ptr1' is uninitialized when used here [-Wuninitialized]程式員可以使用未定義的行為清理器,如果程式員幸運的話,它可能會在運行時檢測到錯誤。在示例程式的情況下:
/app/example.cpp:4:5: runtime error: store to address 0x7ffdda141688 with insufficient space for an object of type 'int' 0x7ffdda141688: note: pointer points here 00 00 00 00 f8 1e 14 da fd 7f 00 00 00 00 00 00 00 00 00 00 03 1f 14 da fd 7f 00 00 7a 1f 14 da ^ SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /app/example.cpp:4:5 in AddressSanitizer:DEADLYSIGNAL ================================================================= ==1==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000000000 bp 0x000000000000 sp 0x7ffdda141598 T0) ==1==Hint: pc points to the zero page. ==1==The signal is caused by a READ memory access. ==1==Hint: address points to the zero page. #0 0x0 (<unknown module>) AddressSanitizer can not provide additional info. SUMMARY: AddressSanitizer: SEGV (<unknown module>) ==1==ABORTING每當代碼發生更改時,程式員都可以自動運行測驗。這不僅有助于確保行為按預期實施,而且還為消毒人員提供了發現錯誤的機會。
uj5u.com熱心網友回復:
為什么您不想將指標初始化為 null。許多代碼在取消參考指標之前檢查空值。
int main()
{
int *ptr1 = nullptr;
if(ptr1 != nullptr)
*ptr1 = 100;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/392693.html
上一篇:從鏈表中的指標存盤字串
