繁体   English   中英

魔术与C ++,va_arg在64位架构上无法正常工作

[英]magic with c++, va_arg doesn't work on 64 bit architecture with double properly

我有一个非常有趣的问题,我的朋友和同事们谁也帮不了我。 因此,让我们看一下下一个c ++代码:

#include <stdio.h>
#include <stdarg.h>
typedef void* VirtualMethodTable;
void funcM(void* __this, ...);
__interface Ix
{
    void __cdecl qq(long a, long b, double x, long c);
};
struct tagInterface
{
    tagInterface()
    {
        VirtualMethodTable* VMT = new VirtualMethodTable[1];
        VMT[0] = (void*)&funcM; //here's funcM assignment
        this->VMT = VMT;
    }
    ~tagInterface(){ delete[] VMT; }
    VirtualMethodTable* VMT;
};
void func1(long a, long b, double x, long c)
{
    //some_logic
}
void funcM(void* __this, ...)
{
    va_list marker;
    va_start(marker, __this);
    marker -= sizeof(__this); // line 1
    tagInterface* inst = va_arg(marker, tagInterface*); //line 2
    //we can comment line 1 and line 2 and it still will work as earlier (doesn't work)
    long l1 = va_arg(marker, long);
    long l2 = va_arg(marker, long);
    double d = va_arg(marker, double);//d = 4.343564450161e-311#DEN, not 3.3
    long l4 = va_arg(marker, long);
    func1(l1, l2, d, l4);
    va_end(marker);
}
long main()
{   
    tagInterface x;
    Ix* ins = (Ix*)((void*)&x);
    long p1 = 1;
    long p2 = 2;
    double p3 = 3.3;
    long p4 = 4;
    ins->qq(p1, p2, p3, p4); //it will call funcM 
}

它在Win32架构上正常工作(Visual Studio 2013,Win7x64)
但是,当我在x64上启动它时,函数funcM中的“ d”变量具有“ 4.343564450161e-311#DEN”的值
其他变量如“ l1”,“ l2”,“ l4”,“ inst”通常会启动。
虽然,我尝试过使用“ float”,但它也不起作用!
我搜索了所有va_arg堆栈溢出问题,但未找到答案!
那我在哪里错了?
谢谢!
更新1 .:
是的,由于“概念堆栈与物理堆栈不匹配”而无法使用
“ d”变量通过xmm3寄存器和va_arg尝试与xmm0一起使用。
希望smbd有时会发现它有用!
更新2.解决问题!
如果是64位程序,则调用约定是不同的:值并不总是通过堆栈传递: https : //msdn.microsoft.com/en-us/library/zthk2dkh.aspx 其中一些通过寄存器传递。 因此,此处不能使用va_list(与堆栈一起使用,并且适用于可变参数函数)。
尝试以下解决方法:

struct ClassIx
{
       virtual void __cdecl qq(...);
};
ClassIx* ins = (ClassIx*)((void*)&x);
ins->qq(p1, p2, p3, p4); //it will call funcM


来自MSDN的Viorel_:
https://social.msdn.microsoft.com/Forums/zh-CN/7a2d9bb5-2b83-4bc5-a018-d7b460fa5550/magic-with-c-vaarg-doesnt-work-on-64-bit-architecture-with-适当的论坛?

va_arg函数必须这样声明和调用。 您不调用va_arg函数,而是调用void __cdecl Ix::qq(long a, long b, double x, long c);

问题的一部分可能是“我只是将参数推入堆栈”。 堆栈不存在。 有一个概念性的C ++调用堆栈(已按时间顺序调用的但尚未返回的所有函数的列表及其参数)和一个物理x64堆栈(RBP / RSP寄存器)。

您的问题是概念堆栈与物理堆栈不匹配。 并非所有功能参数都在物理堆栈上。 var_arg机构具有动态地找出其中的功能的参数是,虽然,这可能意味着参数来参数可变型函数物理栈上。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM