我在静态库中有一个 C 函数,我们称之为 A,具有以下接口:

int A(unsigned int a, unsigned long long b, unsigned int *y, unsigned char *z);

该函数将改变 y 和 z 的值(这是肯定的)。我在动态 C++ 库中使用它,使用 extern“C”。

现在,让我震惊的是:

  • y 已正确设置,z 未更改。我的确切意思是,如果两者都使用(指向的)值 666 进行初始化,则 y 指向的值将在调用后更改,但 z 指向的值不会更改(仍然是 666)。
  • 当从C二进制调用时,此函数可无缝起作用(Z指称的值被修改)。
  • 如果我创建一个虚拟 C 库,其中的函数具有相同的原型,并且我在动态 C++ 库中使用它,那么它会工作得很好。如果我重新使用相同的变量来调用 A(..),我会得到与以前相同的结果,z 不会改变。

我认为以上几点表明我的变量声明并不是一个愚蠢的错误。

我显然被困住了,我无法更改 C 库。您知道可能出现什么问题吗?我正在考虑 C/C++ 接口上的一个问题,例如 char* 的解释方式。

编辑 :我终于知道问题出在哪里了。请看下面我的回答。

有帮助吗?

解决方案 9

首先,非常感谢大家的帮助。感谢您给我提供的众多想法和线索,我终于能够解决这个问题。你的建议帮助我质疑我认为理所当然的事情。

我的问题的简短回答:问题是我的 C++ 库使用了旧版本的 C 库。这个旧版本错过了第四个参数。因此,第四个参数显然从未改变。

现在我意识到这就是问题所在,我感到有点羞愧。然而,我的代码编译良好这一事实误导了我。这是因为 C++ 库是针对正确版本的 C 库进行编译的,但在运行时它使用与我正在使用的另一个库静态链接的旧版本。

C++ Lib (M) ---> dyn C++ lib (N) ---> C lib (P) v.1.0
     |
     ------> C lib (P) v.1.1

(N) 是一个动态库,与(P) 版本1.0 静态链接。编译器接受了从 (M) 到具有 4 个参数的函数的调用,因为我链接到 (P) 版本 1.1,但在运行时它使用旧版本的 (P)。

请随意编辑此答案或问题或要求我这样做。

其他提示

看起来你的 C 库和 C++ 编译器处理方式之间存在差异 长多头. 。我的猜测是,C 库可能是 C89 标准之前的标准,并且实际上处理 64 位 长长 作为 32 位长。您的 C++ 库正确处理它并将 64 位放在调用堆栈上,从而损坏 y 和 z。也许尝试通过 *int A(unsigned int a, unsigned long b, unsigned int *y, unsigned char z), ,看看你会得到什么。

只是一个想法。

这是您所描述的问题中没有明显错误的问题之一,但事情却没有按照您预期的方式进行。

我想你应该 编辑 您的帖子提供了更多信息,以便获得一些合理的答案。特别是,让我们从以下开始:-

  • 此代码适用于什么平台:Windows,Linux,嵌入式或...?
  • C静态库是使用什么编译器?
  • C ++动态库由哪个编译器构建?
  • 可以成功地将库构建的库的C是什么编译器?
  • 您有源级调试器吗?如果是这样,你可以走吗 进入 C ++的C代码。

除非您错误地认为 A 总是修改 Z 指向的数据,否则问题的唯一可能原因是参数传递约定之间的不兼容。“长长”的问题可能暗示事情并不像看上去的那样。

作为最后的手段,您可以比较反汇编的 C++ 调用代码(您说失败)和 C 调用代码(您说成功),或者使用调试器逐步执行 CPU 指令(是的,真的 - 您将学到良好的技能以及解决问题的能力)

据我所知, long long 不是标准 C++ 的一部分,也许这就是你问题的根源。

不知道。尝试调试单步进入 A 并看看会发生什么(汇编代码警报!)

也许您可以将原始函数包装在从 C++ 库调用的 C 库中?

根据您的第 2 点和第 3 点,这似乎可行。

如果没有,它会为您提供另一个调试点以找到更多线索 - 查看哪个库首先出现故障,并检查为什么 2 和 3 可以工作,但这个不行 - 最小的区别是什么?

您还可以尝试检查每种情况下由函数调用设置的堆栈,以检查此处是否存在差异 - 考虑不同的调用约定。

步骤1:将从 C++ 端传递的指针 y 和 z 与 C 函数接收的指针进行比较。

附:我不想听起来很明显,但只是在这里仔细检查一下。我想当您说从 C 二进制文件调用时 z 被修改得很好时,您的意思是 z 指向的数据被修改得很好。指针 y 和 z 本身是按值传递的,因此您无法更改指针。

另一个疯狂的猜测:您确定您正在链接 C 库中该函数的正确实例吗?您的库中是否有几个这样的函数可用?在 C 中,链接器在决定如何解析函数时并不关心返回类型或参数列表——只有名称很重要。所以,如果你有多个同名的函数......

您可以通过编程方式验证函数的身份。创建一个 C 库,使用一些测试参数调用函数 A,该库工作正常并打印指向函数 A 的指针。将库链接到您的 C++ 应用程序中。然后打印从 C++ 代码中看到的指向原始 A 函数的指针,并将该指针与在同一进程中调用时 C 库看到的指针进行比较。

再说一遍,这是显而易见的,但谁知道呢......您确定您正在调用的 C 函数是无状态的,这意味着它的输出仅取决于其输入吗?如果函数不是无状态的,那么可能是“隐藏”状态导致了不同的行为(不更改由 z) 从 C++ 应用程序调用时的函数。

在您的 C++ 程序中,原型是用 extern "C"?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top