为什么通过引用传递的参数未在函数内修改?

时间:2008-09-29 09:04:22

标签: c++ c parameters linker pass-by-reference

我在静态库中有一个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 *的方式。

编辑:我终于找到了问题所在。请参阅下面的答案。

10 个答案:

答案 0 :(得分:4)

看起来你的C库和C ++编译器处理 long longs 的方式有所不同。我的猜测是,C库可能是C89之前的标准,实际上将64位 long long 视为32位长。您的C ++库正确处理它并在调用堆栈上放置64位,从而破坏了y和z。也许尝试通过* int A(unsigned int a,unsigned long b,unsigned int * y,unsigned char z)调用函数,看看你得到了什么。

只是一个想法。

答案 1 :(得分:2)

这是其中一个问题,即你所描述的内容并没有明显错误,但事情并没有按照你期望的方式发挥作用。

我认为您应编辑您的帖子以提供更多信息,以便获得一些明智的答案。特别是,让我们从: -

开始
  • 此代码的平台是: Windows,linux,嵌入的东西 要么 ...?
  • C是什么编译器 静态库用?
  • 什么 编译器是C ++动态库 用?建造?
  • C是什么编译器 哪个可以成功拨打电话 库建有?
  • 你有吗? 源级调试器?如果是的话,可以 你从进入 C代码 C ++。

除非您总是修改Z指向的数据,否则唯一可能的原因是参数传递约定之间不兼容。 “漫长的”问题可能暗示事情并非像他们看似的那样。

作为最后的手段,您可以比较反汇编的C ++调用代码(您说失败)和C调用代码(您说成功),或者使用调试器逐步执行CPU指令(是的,真的 - 你'我将学习一项技巧并解决问题。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

说不上。尝试调试 - 进入A并查看会发生什么(汇编代码警报!)

答案 4 :(得分:1)

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

根据您的第2点和第3点,看起来这可行。

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

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

答案 5 :(得分:1)

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

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

答案 6 :(得分:1)

另一个猜测:您确定要链接到C库中正确的函数实例吗?是不是你的图书馆里有几个这样的功能?在C中,链接器在决定如何解析函数时不关心返回类型或参数列表 - 只有名称很重要。所以,如果你有多个具有相同名称的函数......

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

答案 7 :(得分:1)

同样,一个明显的,但谁知道......你确定你正在调用的C函数是无状态的,这意味着它的输出仅取决于它的输入吗?如果函数不是无状态的,则可能是“隐藏”状态负责从C ++应用程序调用时函数的不同行为(不更改z指向的数据)。

答案 8 :(得分:1)

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

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

我现在有点惭愧,因为我意识到这是问题所在。但是,由于我的代码编译得很好,我被误导了。这是因为C ++库是针对正确版本的C lib编译的,但在运行时它使用了与我正在使用的另一个库静态链接的旧版本。

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)。

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

答案 9 :(得分:0)

在你的C ++程序中,是用extern "C"声明的原型吗?