繁体   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