为什么通过引用传递的参数没有在函数中修改?

hiure 发布于 2018-05-09 c 最后更新 2018-05-09 17:05 202 浏览

我有一个静态库中的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 *的解释方式。 编辑:我终于发现了什么问题。见下面我的答案。
已邀请:

jvitae

赞同来自:

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

raut

赞同来自:

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

funde

赞同来自:

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

weos

赞同来自:

也许你可以将原始函数包装在从C++库调用的C库中? 根据你的观点2和3,这似乎可以奏效。 如果没有,它会给你另一个调试点来寻找更多的线索 - 查看哪个库首次出现故障,并检查为什么2和3能够工作,但这不是 - 最小差异是什么? 您也可以尝试检查由函数调用在每种情况下设置的堆栈,以检查差异是否在这里 - 考虑不同的调用约定。

cnon

赞同来自:

第1步:比较从C++端传递的指针y和z与C函数接收的指针y和z。 附:我不想听起来很明显,但只是在这里仔细检查。我想,当你说从z二进制文件调用z时,z被修改的很好,你的意思是说z指向的数据被修改得很好。指针y和z本身是通过值传递的,所以你不能改变指针。

cut

赞同来自:

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

lsint

赞同来自:

这是其中一个问题,你所描述的内容没有任何明显的错误,但事情并不按照你期望的方式工作。 我认为你应该编辑你的文章以提供更多信息以获得一些明智的答案。特别是,让我们从以下开始: -

  • 这个代码的平台是什么: Windows,Linux,嵌入的东西 要么 ...?
  • C是什么编译器 静态库与内置?
  • 什么 编译器是C++动态库 搭配?
  • C是什么编译器 它可以成功地调用 图书馆建成?
  • 你有没有 源代码级调试器?如果是这样,可以 你从步骤进入C代码 C++。 除非你总是修改Z指向的数据,否则你的问题唯一可能的原因是参数传递约定之间的不兼容。 “漫长的”问题可能暗示事情并非如他们所看到的那样。 作为最后的手段,你可以比较反汇编的C++调用代码(你说失败)和C调用代码(你说成功),或者通过调试器逐步执行CPU指令(是的,真的 - 你会学到一个良好的技能以及解决问题)

cnon

赞同来自:

另一个疯狂的猜测:你确定你在C库中的函数的正确实例链接?难道你的库中有几个这样的函数可用?在C中,链接器在决定如何解析函数时不关心返回类型或参数列表 - 只有名称很重要。所以,如果你有多个同名的函数...... 您可以通过编程验证函数的身份。创建一个C库,用一些测试参数调用你的函数A,并且工作正常,并且打印指向函数A的指针。将库链接到C++应用程序中。然后从C++代码中看到指向原始A函数的指针,并将该指针与您的C库在同一进程中调用时看到的指针进行比较。

cnon

赞同来自:

再次,明显的一个,但是谁知道......你确定你所调用的C函数是无状态的,这意味着它的输出仅依赖于它的输入吗?如果函数不是无状态的,那么可能是因为从C++应用程序调用时,“隐藏”状态负责该函数的不同行为(而不是更改由z指向的数据)。

hiure

赞同来自:

首先,我非常感谢大家的帮助。 由于你给了我很多想法和线索,我终于能够理清这个问题。你的建议帮助我质疑我认为理所当然的东西。 对我的问题的简短回答:问题是我的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)。 随意编辑这个答案或问题或要求我这样做。