提问人: 提问时间:9/29/2008 最后编辑:12 revs, 3 users 54%Barth 更新时间:3/5/2016 访问量:1231
为什么通过引用传递的参数没有在函数中修改?
Why is my parameter passed by reference not modified within the function?
问:
我在静态库中有一个 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* 的方式。
编辑:我终于发现了问题所在。请看下面我的回答。
答:
据我所知,long long 不是标准 C++ 的一部分,也许这就是您问题的根源。
在您的 C++ 程序中,原型是否声明为 ?extern "C"
不知道。尝试调试单步执行 A 并查看会发生什么(汇编代码警报!
评论
也许您可以将原始函数包装在从 C++ 库调用的 C 库中?
根据您的第 2 点和第 3 点,这似乎可以工作。
如果没有,它会给你另一个调试点来寻找更多线索 - 看看故障首先出现在你的哪个库中,并检查为什么 2 和 3 有效,但这没有 - 最小的区别是什么?
您还可以尝试检查函数调用在每种情况下设置的堆栈,以检查差异是否在这里 - 考虑不同的调用约定。
步骤1:将从C++端传递的指针y和z与C函数接收的指针进行比较。
P.S. 我不想听起来很明显,但只是在这里仔细检查一下。我想当你说 z 在从 C 二进制文件调用时被很好地修改时,你的意思是 z 所指向的数据被很好地修改了。指针 y 和 z 本身是按值传递的,因此您无法更改指针。
评论
看起来你的 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++。
除非你对 A 总是修改 Z 指向的数据是错误的,否则你问题的唯一可能原因是参数传递约定之间的不兼容。“长多”的问题可能暗示事情并不像看起来那样。
作为最后的手段,您可以比较反汇编的 C++ 调用代码(您说失败)和 C 调用代码(您说成功),或者使用调试器逐步执行 CPU 指令(是的,真的 - 您将学到很好的技能并解决问题)
另一个疯狂的猜测:你确定你正在链接到你的 C 库中函数的正确实例吗?难道您的库中有几个这样的功能可用吗?在 C 语言中,链接器在决定如何解析函数时并不关心返回类型或参数列表——只有名称很重要。因此,如果您有多个同名函数...
可以通过编程方式验证函数的标识。创建一个 C 库,该库使用一些测试参数调用函数 A,该库工作正常,并打印指向函数 A C++的指针。然后打印指向从 C++ 代码中看到的原始 A 函数的指针,并将指针与在同一进程中调用时 C 库看到的指针进行比较。
再一次,一个显而易见的,但谁知道呢......您确定您调用的 C 函数是无状态的,这意味着它的输出仅取决于其输入吗?如果函数不是无状态的,则可能是“隐藏”状态导致从 C++ 应用调用时函数的不同行为(不更改指向的数据)。z
首先,非常感谢大家的帮助。 多亏了你给我的众多想法和线索,我终于能够解决这个问题。你的建议帮助我质疑我所认为的理所当然的事情。
对我的问题的简短回答:问题是我的C++库使用了旧版本的C库。这个旧版本错过了第 4 个参数。因此,第四个论点显然从未改变过。
我现在有点惭愧,因为我意识到这就是问题所在。但是,我被我的代码编译良好的事实所误导。这是因为 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)。
请随意编辑此答案或问题,或要求我这样做。
评论