2

我有一个位于共享对象中的函数,并dlsym从主程序加载和执行。(共享对象和主程序都是C++)

这个函数有可能返回std::unique_ptr吗?

共享对象功能 -

extern "C" {
    unique_ptr<Obj> some_function() {
        return make_unique<Obj>();
    }
}

主程序:

void main_flow() {
    auto handle = dlopen(...);
    FuncPtr func = dlsym(handle, "some_function");
    unique_ptr<Obj> func();
}
4

1 回答 1

4

是的,是的,有很多警告。首先,在 DSO 接口中使用 boost 或 STL 有点危险。

  1. std::unique_ptr 在编译器之间有所不同
  2. std::unique_ptr 在 C++ 版本之间有所不同
  3. std::unique_ptr 可能在调试/发布版本之间有所不同。

这意味着如果您在 DSO 接口中使用 STL 或 boost,则所有 exe 和 dsos 必须使用完全相同版本的 C++ 运行时,使用相同的构建标志编译(如果您喜欢,则使用相同版本的 boost)。

我建议在 Visual Studio 上使用警告级别 4,它可以很好地列出 DSO 接口中的所有上述问题(作为 C4251 警告)

至于您的问题,是的,该函数将返回一个 std::unique_ptr,但是您现在正在 DSO 中分配内存,您可能会在 exe 中释放这些内存。这在 Windows 世界中可能非常糟糕,您可能会发现调试版本具有不同的堆。尝试在 EXE 堆中释放 DSO 分配的对象将引发运行时错误,但通常仅在调试版本中。

你的主要应该是这样的:

void main_flow() {
  auto handle = dlopen(...);
  FuncPtr func = (FuncPtr)dlsym(handle, "some_function");
  unique_ptr<Obj> obj = func();
}  

不过就个人而言,我建议只返回一个裸指针,并在您的 exe 中对其进行 make_unique 。这至少消除了 C4251 问题,尽管您可能会被堆问题所困扰(除非您将类类型的析构函数设为虚拟)

于 2019-07-09T06:53:08.987 回答