使用函数指针时,跨函数调用未正确保存ESP

时间:2018-06-19 13:04:19

标签: c++ function-pointers

我正在尝试创建一个将成员函数的函数指针保存到数组的程序。然后,程序从该数组中获取函数指针,并调用该指针指向的函数。只要使用的成员函数没有任何参数,此方法就起作用。当我给它参数时,Visual Studio 2017中会发生以下错误:

  

运行时检查失败#0-在整个函数调用中ESP的值未正确保存。这通常是由于使用一种调用约定声明的函数和使用另一种调用约定声明的函数指针进行调用的结果。

我的代码是:

typedef uint8_t byte;

template<typename T>
class Test
{
public:
    void FuncTest(byte* data)
    {
        cout << (T)(0.0625f) << endl;
    }
};

typedef Test<float> fTest;
typedef Test<long long> lTest;

int main()
{
    byte data[1024];

    {
        void (fTest::*ffp)(byte*) = &fTest::FuncTest;
        //void (lTest::*lfp)(byte*) = &lTest::FuncTest;

        printf("%p\n", ffp);

        memcpy(&data[0], (int64*)&ffp, sizeof(int64));
    }

    {
        int64 pData;

        memcpy(&pData, &data[0], sizeof(int64));

        void(*func_pointer)(byte*) = (void(*) (byte*))(pData);

        printf("%p\n", pData);

        func_pointer(nullptr);
    }
}

如果有人可以提供帮助,将不胜感激。

1 个答案:

答案 0 :(得分:1)

忽略数组中的代码实际上就是:

void (Test::*ffp)(byte*) = &fTest::FuncTest;
void* pData = (void*)ffp;
void(*func_pointer)(byte*) = (void(*) (byte*))(pData);
func_pointer(nullptr);

ffp的类型本质上是(尽管不完全是由于不同的调用约定)void (fTest*, byte*)func_pointer的类型不匹配。

解决方案是将std::functionstd::bind或lambda一起使用以转换函数签名。例如:

std::vector<std::function<void(byte*)>> functions;
fTest test;
functions.push_back([=](byte* data){ test.FuncTest(data); });
functions.front()(nullptr);