如何调试“传递给 C 运行时函数的参数无效”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36968475/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:39:51  来源:igfitidea点击:

how to debug "Invalid parameter passed to C runtime function"?

c++debugging

提问by Joran Dox

Background

背景

I've got about a terabyte of files with raw data, with a relatively small subset of labelled data. I've written c++ code (calling some ancient MSVC++2003 code I heavily modified to get it to compile on recent compilers) to aggregate the annotated data slices.

我有大约 1 TB 的原始数据文件,以及相对较小的标记数据子集。我已经编写了 C++ 代码(调用了一些古老的 MSVC++2003 代码,我对其进行了大量修改以使其在最近的编译器上编译)来聚合带注释的数据切片。

A big part of that labelled data is concentrated in one file, but that file turns out to be the one where my program crashes.

标记数据的很大一部分集中在一个文件中,但结果证明该文件是我的程序崩溃的地方。

Problem

问题

I'm getting

我越来越

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

In my Qt output window, and windows tells me the same in a popup, but at this point it's too late to get any useful info out of the executable / debugger it seems (though I'm not experienced at all with Qt's debugger).

在我的 Qt 输出窗口中,windows 会在弹出窗口中告诉我相同的信息,但此时从可执行文件/调试器中获取任何有用的信息似乎为时已晚(尽管我对 Qt 的调试器完全没有经验)。

What I have tried

我试过的

I've googled all over and found plenty of people with this error message but it's so generic that none of their issues could be the same as mine, and there's such a long list of different C runtime functions that sifting through all of them is slow and it doesn't seem to help.

我到处搜索,发现很多人都有这个错误消息,但它太笼统了,他们的问题都不会和我的一样,而且有很长的不同 C 运行时函数列表,筛选所有这些函数都很慢它似乎没有帮助。

My question

我的问题

"Find a man a bug, and you help him for a day. Teach a man to debug and you help him for a lifetime. Post the way on stackoverflow and you help many men and get a lot of upvotes."

“找到一个人一个错误,你可以帮助他一天。教一个人调试,你可以帮助他一生。在 stackoverflow 上发布方法,你帮助很多人并获得很多赞成。”

Is there a generic method to find what C runtime function the problem was and what the argument was? Did I miss some fancy debugger features? Is there anything else you could recommend or info I could provide?

是否有通用方法来查找问题所在的 C 运行时函数以及参数是什么?我是否错过了一些花哨的调试器功能?您还有什么可以推荐的或我可以提供的信息吗?

I'd hope to get a catch-all answer to this to help everyone with this problem, not just me, but I'll be glad if I'm helped too of course.

我希望得到一个包罗万象的答案来帮助每个人解决这个问题,不仅仅是我,但如果我也得到帮助,我会很高兴。

Specific to my problem:

具体到我的问题:

My stack trace is as follows:

我的堆栈跟踪如下:

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

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

and gdb can't get a better trace it seems (anything I try to do with it gets me a timeout error).

并且 gdb 似乎无法获得更好的跟踪(我尝试用它做的任何事情都会导致超时错误)。

After trying a couple more functions just to be sure everything gave a timeout trying "backtrace" once again did give me a result. I guess I just never put this much time in gdb after it timeouting on me once.

在尝试了更多功能以确保一切都超时后,再次尝试“回溯”确实给了我一个结果。我想我只是在 gdb 超时一次后从未在 gdb 中投入这么多时间。

That said, I mightbe able to find something with this new info. Consider my specific problem closed, but my general point is still valid I believe: I've now found the function with the problem (I think), but not why it is a problem, nor what the invalid parameter is. Even better, I've traced it to a line where it says "throw 1". So now I'm assuming windows/Qt translates that to the "invalid parameter". But it's not true.

也就是说,我也许可以通过这些新信息找到一些东西。考虑我的特定问题已关闭,但我相信我的一般观点仍然有效:我现在已经找到了有问题的函数(我认为),但不是为什么它是一个问题,也不是无效参数是什么。更好的是,我已经将其追溯到“throw 1”的一行。所以现在我假设 windows/Qt 将其转换为“无效参数”。但事实并非如此。

It can just be some bad code, it does not even need to be a C function, and nothing needs to be wrong with your parameters.

它可以只是一些糟糕的代码,它甚至不需要是一个 C 函数,你的参数也不需要有任何错误。

...

...

#17 0x00c17d72 in libstdc++-6!.cxa_throw () from C:\Qt\5.5\mingw492_32\bin\libstdc++-6.dll No symbol table info available. ...

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

采纳答案by William Gerecke

Personally, on a Linux terminal, I use gcc for compiling and gdb for debugging. To compile a program with debugging options using gcc, you simply have to add a -gto your other flags. Ex:gcc file.c -o file -std=c99 -g. You can then type gdb fileand you enter into an interactive debugger. Among other helpful things, you can run the program, call functions and insert breakpoints. For a full and well explained usage go to this website-http://www.tutorialspoint.com/gnu_debugger/index.htm

就我个人而言,在 Linux 终端上,我使用 gcc 进行编译,使用 gdb 进行调试。要使用 gcc 编译带有调试选项的程序,您只需将 a 添加-g到其他标志。例如:gcc file.c -o file -std=c99 -g。然后您可以键入gdb file并进入交互式调试器。除了其他有用的功能外,您还可以运行程序、调用函数和插入断点。有关完整且详细解释的用法,请访问此网站 - http://www.tutorialspoint.com/gnu_debugger/index.htm

回答by Pavel P

Since the log is printed to the debug console then it should be reported by OutputDebugStringAfunction. You can place a breakpoint on the function to see who results in that log. To place a breakpoint on a function you can Ctrl+Bin Visual Studio and enter function name:

由于日志打印到调试控制台,因此应按OutputDebugStringA功能报告。您可以在该函数上放置一个断点,以查看该日志中的结果。要在函数上放置断点,您可以Ctrl+B在 Visual Studio 中输入函数名称:

enter image description here

在此处输入图片说明

But this might not work, or you may have too many other messages logged using OutputDebugStringA. Usually Invalid parameter passed to C runtime functionis reported by _invalid_parameter, so, you may as well try to place a breakpoint on _invalid_parameterfunction. This might not work as well because it could be reported from some other system dll that your process links to: ntdll.dll, KernelBase.dlletc. To place a breakpoint on a function exported by a dll you need to use: <dll>!<exportname>:

但这可能不起作用,或者您可能使用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

All of these are different functions and you can see their addresses:

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

enter image description here

在此处输入图片说明

In my case only when I set a breakpoint on ntdll.dll!__invalid_parameterI was able to see backtrace and the log message was caused by GetAdaptersAddresseswinapi. The reason breakpoint on OutputDebugStringAwasn't helpful was because the log was printed through DbgPrintapi. Placing breakpoint on DbgPrintworks in this case.

在我的情况下,只有当我在上设置断点时ntdll.dll!__invalid_parameter才能看到回溯并且日志消息是由GetAdaptersAddresseswinapi引起的。断点OutputDebugStringA没有帮助的原因是因为日志是通过DbgPrintapi打印的。DbgPrint在这种情况下,在作品上放置断点。

回答by mcgoo

In Visual Studio 2017 at least, you can hit CTRL+B and add a function breakpoint on _invalid_parameter. This will stop your program at the point where the message would have been logged, which will let you find the offending function in the call stack. It will work even if someone else's code undoes your call to _CrtSetReportMode().

至少在 Visual Studio 2017 中,您可以按 CTRL+B 并在_invalid_parameter. 这将在消息将被记录的位置停止您的程序,这将让您在调用堆栈中找到有问题的函数。即使其他人的代码撤消了您对_CrtSetReportMode().

回答by Joran Dox

Things I learned from this question (and that might help people searching for this question) :

我从这个问题中学到的东西(这可能有助于人们搜索这个问题):

  1. Turns out that this error could be traced back to a line of code saying
    throw 1;
    This means It can just be some bad code, it does not even need to be a C function, and nothing needs to be wrong with your parameters. Searching your code and libraries' source for "throw"
  2. Turns out that getting timeouts on gdb are not an indicator of anything. Keep trying things and retrying and maybe at one time you might get a stack trace.
  1. 事实证明,这个错误可以追溯到一行代码
    throw 1;
    这意味着它可以只是一些糟糕的代码,它甚至不需要是一个 C 函数,并且你的参数不需要有任何错误。在你的代码和库的源代码中搜索“throw”
  2. 事实证明,在 gdb 上超时并不能说明任何事情。继续尝试并重试,也许有一次您可能会得到堆栈跟踪。

回答by LMSingh

I ran into this same error message "Invalid parameter..." while debugging a windows driver. The technique on this page, even though for Windows and not exactly addressing for this question, might be useful to someone who is looking for this particular error message. IOW HTH..

在调试 Windows 驱动程序时,我遇到了同样的错误消息“无效参数...”。此页面上的技术,即使对于 Windows 并没有完全解决此问题,也可能对正在寻找此特定错误消息的人有用。IOW HTH..

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

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

So in summary you have to narrow down specific to your environment where a debug string is being output by possibly a debugging "helper" library function. Once known, set a breakpoint there and then look back up the call stack. IMHO, it's a very clever solution to what can be a tough location to find.

因此,总而言之,您必须缩小特定于您的环境的范围,其中可能是调试“帮助程序”库函数正在输出调试字符串。一旦知道,在那里设置一个断点,然后查看调用堆栈。恕我直言,这是一个非常聪明的解决方案,可以解决很难找到的位置。