簡體   English   中英

為什么 Mingw64 異常<stdio.h>而不是在我的代碼中?

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

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