[英]Why Mingw64 exeption in <stdio.h> and not in my code?
我知道我在下面顯示的代碼不正確,但我想知道為什么 stdio.h 被歸咎於:
<stdio.h> 腳本中出現異常:
__retval = __mingw_vfprintf( stdout, __format, __local_argv );
分段錯誤 int 標准輸出。
初學者的代碼,實際上:
#include <stdio.h>
int main()
{
printf(12345);
return 0;
}
我知道這可能不正確,但我認為,錯誤應該出現在我的文件中,而不是腳本 <stdio.h> 文件中。
對我來說主要的問題是,為什么如果我調用 printf(Hello World),它不會顯示 <stdio.h> 錯誤,但它會顯示 12345? 今天開始學C語言,沒有練習,不好意思)
問題當然出在您的代碼中:
printf(12345);
printf
函數的第一個參數必須是格式字符串。 在您的情況下,您將整數轉換為指針(該指針不太可能引用有效內存)。 printf
函數試圖解除它的引用,你得到一個段錯誤。
要打印 12345,您需要:
printf("%d", 12345);
我的主要問題是,為什么如果我調用 printf(Hello World),它不會向我顯示 <stdio.h> 錯誤
printf("hello world");
是正確的,因為第一個參數是有效的 C 字符串。
首先,這段代碼是無效的C。正確配置的編譯器( https://software.codidact.com/posts/282565 )可能會簡單地拒絕生成程序,因為“來自整數的指針/來自指針的整數沒有演員表”的問題。
當您在寬松的非標准模式下運行它們時,像 gcc/mingw 這樣的一些編譯器可能允許從整數到指針的隱式轉換。 然后將12345
作為printf
期望的char*
格式字符串的地址值。
至於為什么代碼在某些 stdio.h 標頭中崩潰,首先取決於您如何執行代碼 - 您必須在調試器(mingw/gdb)中運行它才能知道它在哪里崩潰,否則操作系統只會說訪問沖突(Windows)或段錯誤(*nix)。
在 mingw64/gdb 中運行它時,我可以將崩潰重現為:
#2 0x00007ff7f4471817 in printf (__format=0x3039 <error: Cannot access memory at address 0x3039>) at c:/program files/mingw-w64/x86_64-w64-mingw32/include/stdio.h:372
它指向 stdio.h 中的printf
函數,結果證明它只是內部庫函數__mingw_vfprintf
的一個薄包裝器:
__retval = __mingw_vfprintf( stdout, __format, __local_argv );
這與我的 mingw64 允許我進入 C 代碼一樣深,可能此函數的定義位於靜態鏈接庫中,並且沒有我可以訪問的 C 代碼。
至於機器代碼,它在這個特定的匯編指令上崩潰:
0x7ff7f44758e2 movzx eax,BYTE PTR [rax]
這似乎發生在printf
調用的__cdecl
調用約定所需的堆棧期間。 發生這種情況時, rax
包含幻數0x3039
aka 12345
。 究竟是什么導致 MMU 崩潰,我不知道,但我們確實知道0x3039
不是一個有效地址(並且未對齊)。 一些 x86 匯編器大師也許可以解釋為什么在這個特定的 ISA 中會發生這種情況……但這對於普通 C 程序員來說已經太深奧了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.