c++ - std::function 的运行时实现

标签 c++

为了安全起见,我已经在我的 DLL 调用中使用了旧式函数指针,如下所示:

// DLL
typedef int (__stdcall* ty)();
void test(ty t)
{
    if (t)
    {
        int r = t(); 
        ....
    }
}
而我可以使用这个:
void test(std::function<int()> t)
{
}
然而,众所周知,后者使用 type erasure . std::function不能是原始函数指针(因为它可以传递一个具有捕获的 lambda,因此不能是原始指针)。
因此,在 Visual Studio 中,在 Release模式下使用 DLL 构建,其函数签名包含 std::function在 Debug模式下从可执行构建中使用时崩溃,反之亦然。即使它是调试或 Release模式,行为也不相同。有时它会崩溃,有时它会工作。
是否有定义的运行时行为,我们可以依赖它来使用 std::function ?或者这是编译器专门根据我传递给它的内容而专门编译的东西,因此不能预先假定运行时行为?
在汇编级别,必须知道预编译单元上的函数签名。据我所知std::function运行时实现没有很好的定义。
所以,例如,当我编译时,然后
void test(std::function<int()> t)
可以接受任何参数,如 []() -> int, [&]() -> int, [=]() -> int等通过类型删除。但是,当这是预编译的,因此只在运行时,可以接受什么? std::function 是如何实现的?使用类指针?有明确定义的方法吗?
我不是在寻找必然与 VS 相关的解决方案,而是在寻找 std::function 的标准定义。 ,如果有的话。

最佳答案

So, in Visual studio, using a DLL build in release mode with a function signature that contains std::function crashes, when used from an executable build in debug mode and vice versa.


这永远不会起作用,因为它会更改 ABI。

Even if it's both debug or release mode, the behavior is not the same. Sometimes it crashes, some times it works.


如果您注意编译器标志、依赖的静态库与动态库、C 和 C++ 标准库的编译方式、异常等,这可能会起作用。这是一个复杂的话题,取决于编译器供应商的保证。

Is there a defined run-time behaviour that we can rely on to use std::function?


一般来说,最好的选择(也是为其他语言创建绑定(bind)最有用的选择)是避免使用 C++ 接口(interface)并使用普通类型的普通 C 接口(interface)。
也就是说,如果您想传递 C++ 类型,请将它们作为不透明类型传递,并且只从一侧操作它们。

I'm not looking for a VS-related solution, but a standard definition of std::function, if any.


C++ 标准没有强制任何特定的 ABI,也没有给出绝大多数类型的数据成员等实现细节。
这就是为什么即使您以完全相同的方式编译所有内容,混合不同的 STL 库也是一个问题。

关于c++ - std::function 的运行时实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65382150/

相关文章:

c++ - for循环的缺点

c++ - 没有除了风格和性能的练习?

c++ - "Vorbis Extradata missing"尝试获取有关编解码器的流信息时

c++ - 删除/删除 vector 项的最有效/最快的方法

c++ - 为什么会有注入(inject)的类名?

无论用户输入什么,C++ cin 都会为整数返回 0

c++ - 从构造函数的参数中推导出模板 size_t

c++ - 调试这个c++程序

c++ - 编译器的健壮性……天真

c++ - 如何在Windows上使用MinGW编译C++?