簡體   English   中英

如何調試“傳遞給 C 運行時函數的參數無效”?

[英]how to debug “Invalid parameter passed to C runtime function”?

背景

我有大約 1 TB 的原始數據文件,以及相對較小的標記數據子集。 我已經編寫了 C++ 代碼(調用了一些古老的 MSVC++2003 代碼,我對其進行了大量修改以使其在最近的編譯器上編譯)來聚合帶注釋的數據切片。

標記數據的很大一部分集中在一個文件中,但結果證明該文件是我的程序崩潰的地方。

問題

我得到

Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.
terminate called after throwing an instance of 'int'

在我的 Qt 輸出窗口中,windows 會在彈出窗口中告訴我相同的信息,但此時從可執行文件/調試器中獲取任何有用的信息似乎為時已晚(盡管我對 Qt 的調試器完全沒有經驗)。

我試過的

我到處搜索,發現很多人都有這個錯誤消息,但它太籠統了,他們的問題都不會和我的一樣,而且有很長的不同 C 運行時函數列表,篩選所有這些函數都很慢它似乎沒有幫助。

我的問題

“找到一個人一個錯誤,你可以幫助他一天。教一個人調試,你可以幫助他一生。在 stackoverflow 上發布方法,你幫助很多人並獲得很多贊成。”

是否有通用方法來查找問題所在的 C 運行時函數以及參數是什么? 我是否錯過了一些花哨的調試器功能? 您還有什么可以推薦的或我可以提供的信息嗎?

我希望得到一個包羅萬象的答案,以幫助每個人解決這個問題,不僅僅是我,但如果我也得到幫助,我會很高興。

具體到我的問題:

我的堆棧跟蹤如下:

0 ntdll!DbgBreakPoint 0x7727000d
1 ntdll!DbgUiRemoteBreakin 0x772ff156
2 ?? 0x6f06eaa1
3 KERNEL32!BaseThreadInitThunk 0x7501338a
4 ntdll!RtlInitializeExceptionChain 0x77299902
5 ntdll!RtlInitializeExceptionChain 0x772998d5
6 ??

並且 gdb 似乎無法獲得更好的跟蹤(我嘗試用它做的任何事情都會導致超時錯誤)。

在嘗試了更多功能以確保一切都超時后,再次嘗試“回溯”確實給了我一個結果。 我想我只是在 gdb 超時一次后從未在 gdb 中投入這么多時間。

也就是說,我也許可以通過這些新信息找到一些東西。 考慮我的具體問題已關閉,但我相信我的一般觀點仍然有效:我現在已經找到了有問題的函數(我認為),但不是為什么它是一個問題,也不是無效參數是什么。 更好的是,我已經將其追溯到“throw 1”的一行。 所以現在我假設 windows/Qt 將其轉換為“無效參數”。 但事實並非如此。

它可以只是一些糟糕的代碼,它甚至不需要是一個 C 函數,你的參數也不需要有任何錯誤。

...

#17 0x00c17d72 in libstdc++-6!.cxa_throw () from C:\\Qt\\5.5\\mingw492_32\\bin\\libstdc++-6.dll 沒有可用的符號表信息。 ...

由於日志打印到調試控制台,因此應該由OutputDebugStringA函數報告。 您可以在該函數上放置一個斷點以查看該日志中的結果。 要在函數上放置斷點,您可以在 Visual Studio 中Ctrl+B並輸入函數名稱:

在此處輸入圖片說明

但這可能不起作用,或者您可能使用OutputDebugStringA記錄了太多其他消息。 通常Invalid parameter passed to C runtime function_invalid_parameter報告的,因此,您不妨嘗試在_invalid_parameter函數上放置一個斷點。 這可能無法正常工作,因為它可能會從您的進程鏈接到的某些其他系統 dll 報告: ntdll.dllKernelBase.dll等。要在 dll 導出的函數上放置斷點,您需要使用: <dll>!<exportname> :

_invalid_parameter
ntdll.dll!__invalid_parameter
KernelBase.dll!__invalid_parameter
msvcrt.dll!__invalid_parameter
ucrtbase.dll!__invalid_parameter

所有這些都是不同的功能,您可以看到它們的地址:

在此處輸入圖片說明

在我的情況下,只有當我在ntdll.dll!__invalid_parameter上設置斷點時,我才能看到回溯並且日志消息是由GetAdaptersAddresses winapi引起的。 OutputDebugStringA斷點沒有幫助的原因是因為日志是通過DbgPrint api 打印的。 在這種情況下,在DbgPrint上放置斷點有效。

至少在 Visual Studio 2017 中,您可以按 CTRL+B 並在_invalid_parameter上添加函數斷點。 這將在消息將被記錄的位置停止您的程序,這將讓您在調用堆棧中找到有問題的函數。 即使其他人的代碼撤消了您對_CrtSetReportMode()調用,它也會起作用。

我從這個問題中學到的東西(這可能有助於人們搜索這個問題):

  1. 原來這個錯誤可以追溯到一行代碼說
    扔1;
    這意味着它可以只是一些糟糕的代碼,它甚至不需要是一個 C 函數,並且你的參數不需要有任何錯誤。 在你的代碼和庫的源代碼中搜索“throw”
  2. 事實證明,在 gdb 上超時並不能說明任何事情。 繼續嘗試並重試,也許有一次您可能會得到堆棧跟蹤。

就我個人而言,在 Linux 終端上,我使用 gcc 進行編譯,使用 gdb 進行調試。 要使用 gcc 編譯帶有調試選項的程序,您只需將-g添加到其他標志。 例如: gcc file.c -o file -std=c99 -g 然后,您可以鍵入gdb file並進入交互式調試器。 除了其他有用的功能外,您還可以運行程序、調用函數和插入斷點。 有關完整且詳細解釋的用法,請訪問此網站 - http://www.tutorialspoint.com/gnu_debugger/index.htm

在調試 Windows 驅動程序時,我遇到了同樣的錯誤消息“無效參數...”。 此頁面上的技術,即使對於 Windows 並沒有完全解決此問題,也可能對正在尋找此特定錯誤消息的人有用。 IOW HTH..

http://dennisyurichev.blogspot.com/2013/05/warning-invalid-parameter-passed-to-c.html

因此,總而言之,您必須縮小特定於您的環境的范圍,其中可能是調試“幫助程序”庫函數正在輸出調試字符串。 一旦知道,在那里設置一個斷點,然后查看調用堆棧。 恕我直言,這是一個非常聰明的解決方案,可以解決很難找到的位置。

如果您僅使用 MinGW(沒有 Visual Studio 構建內容)。 在構建調試版本時,嘗試為控制台子系統而不是 Windows 子系統編譯您的應用程序。 在這種情況下,當一個無效的參數被傳遞給一個 C 函數時,該函數將失敗並且會觸發你的錯誤處理代碼,而不是標准庫的錯誤框,這應該讓你更好地控制發生的事情。

暫無
暫無

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

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