简体   繁体   English

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

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

Background背景

I've got about a terabyte of files with raw data, with a relatively small subset of labelled data.我有大约 1 TB 的原始数据文件,以及相对较小的标记数据子集。 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.我已经编写了 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?是否有通用方法来查找问题所在的 C 运行时函数以及参数是什么? Did I miss some fancy debugger features?我是否错过了一些花哨的调试器功能? Is there anything else you could recommend or info I could provide?您还有什么可以推荐的或我可以提供的信息吗?

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 0 ntdll!DbgBreakPoint 0x7727000d
1 ntdll!DbgUiRemoteBreakin 0x772ff156 1 ntdll!DbgUiRemoteBreakin 0x772ff156
2 ?? 2 ?? 0x6f06eaa1 0x6f06eaa1
3 KERNEL32!BaseThreadInitThunk 0x7501338a 3 KERNEL32!BaseThreadInitThunk 0x7501338a
4 ntdll!RtlInitializeExceptionChain 0x77299902 4 ntdll!RtlInitializeExceptionChain 0x77299902
5 ntdll!RtlInitializeExceptionChain 0x772998d5 5 ntdll!RtlInitializeExceptionChain 0x772998d5
6 ?? 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 might be 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".更好的是,我已经将其追溯到“throw 1”的一行。 So now I'm assuming windows/Qt translates that to the "invalid parameter".所以现在我假设 windows/Qt 将其转换为“无效参数”。 But it's not true.但事实并非如此。

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 没有可用的符号表信息。 ... ...

Since the log is printed to the debug console then it should be reported by OutputDebugStringA function.由于日志打印到调试控制台,因此应该由OutputDebugStringA函数报告。 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+B in Visual Studio and enter function name:要在函数上放置断点,您可以在 Visual Studio 中Ctrl+B并输入函数名称:

在此处输入图片说明

But this might not work, or you may have too many other messages logged using OutputDebugStringA .但这可能不起作用,或者您可能使用OutputDebugStringA记录了太多其他消息。 Usually Invalid parameter passed to C runtime function is reported by _invalid_parameter , so, you may as well try to place a breakpoint on _invalid_parameter function.通常Invalid parameter passed to C runtime function_invalid_parameter报告的,因此,您不妨尝试在_invalid_parameter函数上放置一个断点。 This might not work as well because it could be reported from some other system dll that your process links to: ntdll.dll , KernelBase.dll etc. To place a breakpoint on a function exported by a dll you need to use: <dll>!<exportname> :这可能无法正常工作,因为它可能会从您的进程链接到的某些其他系统 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:所有这些都是不同的功能,您可以看到它们的地址:

在此处输入图片说明

In my case only when I set a breakpoint on ntdll.dll!__invalid_parameter I was able to see backtrace and the log message was caused by GetAdaptersAddresses winapi .在我的情况下,只有当我在ntdll.dll!__invalid_parameter上设置断点时,我才能看到回溯并且日志消息是由GetAdaptersAddresses winapi引起的。 The reason breakpoint on OutputDebugStringA wasn't helpful was because the log was printed through DbgPrint api. OutputDebugStringA断点没有帮助的原因是因为日志是通过DbgPrint api 打印的。 Placing breakpoint on DbgPrint works in this case.在这种情况下,在DbgPrint上放置断点有效。

In Visual Studio 2017 at least, you can hit CTRL+B and add a function breakpoint on _invalid_parameter .至少在 Visual Studio 2017 中,您可以按 CTRL+B 并在_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() .即使其他人的代码撤消了您对_CrtSetReportMode()调用,它也会起作用。

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;扔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.这意味着它可以只是一些糟糕的代码,它甚至不需要是一个 C 函数,并且你的参数不需要有任何错误。 Searching your code and libraries' source for "throw"在你的代码和库的源代码中搜索“throw”
  2. Turns out that getting timeouts on gdb are not an indicator of anything.事实证明,在 gdb 上超时并不能说明任何事情。 Keep trying things and retrying and maybe at one time you might get a stack trace.继续尝试并重试,也许有一次您可能会得到堆栈跟踪。

Personally, on a Linux terminal, I use gcc for compiling and gdb for debugging.就我个人而言,在 Linux 终端上,我使用 gcc 进行编译,使用 gdb 进行调试。 To compile a program with debugging options using gcc, you simply have to add a -g to your other flags.要使用 gcc 编译带有调试选项的程序,您只需将-g添加到其他标志。 Ex: gcc file.c -o file -std=c99 -g .例如: gcc file.c -o file -std=c99 -g You can then type gdb file and you enter into an interactive debugger.然后,您可以键入gdb file并进入交互式调试器。 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有关完整且详细解释的用法,请访问此网站 - http://www.tutorialspoint.com/gnu_debugger/index.htm

I ran into this same error message "Invalid parameter..." while debugging a windows driver.在调试 Windows 驱动程序时,我遇到了同样的错误消息“无效参数...”。 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.此页面上的技术,即使对于 Windows 并没有完全解决此问题,也可能对正在寻找此特定错误消息的人有用。 IOW HTH.. 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.恕我直言,这是一个非常聪明的解决方案,可以解决很难找到的位置。

If you are using MinGW only (no Visual Studio build stuff).如果您仅使用 MinGW(没有 Visual Studio 构建内容)。 Try compiling your application for the Console subsystem instead of the Windows subsystem when building debug version.在构建调试版本时,尝试为控制台子系统而不是 Windows 子系统编译您的应用程序。 In that case when an invalid argument is passed to a C function the function will fail and will trip your error handling code instead of the standard library's error box which should give you better control over what is happening.在这种情况下,当一个无效的参数被传递给一个 C 函数时,该函数将失败并且会触发你的错误处理代码,而不是标准库的错误框,这应该让你更好地控制发生的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM