【问题标题】:Problem passing std::string though DLL boundaries with visual studio通过 Visual Studio 的 DLL 边界传递 std::string 的问题
【发布时间】:2019-05-14 17:32:57
【问题描述】:

我有一个包含如下代码的 DLL:

class Info {
    int a
    int b
    int c
    std::string str1;
    std::string str2;
};

__declspec(dllexport) class C {
    Info getInfo();
}

我使用 Visual Studio 2015 编译此代码,调用 C::getInfo() 在我的系统上运行良好。

现在其他人正在尝试使用 DLL,并且他也在使用 Visual Studo 2015。调用顺利,但字符串不包含任何可访问的数据。连调试器都报“读取字符串时出错”,读取时程序崩溃。

std::vector 也有类似的问题,我可以通过内联创建向量的代码来解决。

在我看来,这看起来像是其他人使用了不同的 STL 版本,或者编译器以某种方式为 std::string 生成了不同的内存布局(尽管他声称使用默认设置)。

这可能吗?我看到 VS 2015 有不同的更新,我们可能没有安装相同的更新。

有解决此问题的建议吗?我不能在不严重破坏 API 的情况下转移到 char*。大多数用户甚至不使用 Visual Studio(或 Windows),所以直到现在这还不是问题。

【问题讨论】:

  • 需要mcve。请务必使用正确的标志:docs.microsoft.com/en-us/cpp/build/reference/…
  • 你确定没有混合调试和发布吗?这意味着您必须分别提供调试 dll 和发布 dll,并且用户必须使用正确的。
  • 是的,只要您使用相同的运行时版本,它就应该可以工作。更新应该没关系。确保工具集实际上设置为“VC140”,并且您使用的运行时链接类型与 Dan 在上面发布的相同(您不能混合调试和发布代码)。
  • @Aconcagua 根本无法运行
  • 调试和发布的运行时不兼容。在调试模式下,标准库和运行时中有额外的数据来帮助调试。

标签: c++ visual-studio dll stl dllexport


【解决方案1】:

这就是我害怕的生活。除非您有完全相同的编译器(包括 C++ 标准库)和编译器设置,否则不能保证这能正常工作。从 C++ 标准的角度来看,我不相信即使这样也能保证工作。在 C++ 中构建 ABI 几乎是不可能的。在您的具体示例中,不能保证 struct 将使用相同的对齐特征构建。 sizeof(std::string) 变化很大,部分原因是短字符串优化甚至可以编译器配置。

替代方案:

  1. 将 C 链接用于导出的函数和由调用者分配和释放的 char* 样式接口(参见 Windows API)。 (永远不要在客户端分配内存并在 dll 中取消分配,反之亦然。)

  2. 确保库的用户可以从源文件构建它。考虑作为静态库而不是动态库进行分发,因为前者更容易使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    • 2013-07-26
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 2021-12-29
    • 1970-01-01
    相关资源
    最近更新 更多