【问题标题】:C string through dll boundaries通过 dll 边界的 C 字符串
【发布时间】:2016-04-01 06:31:59
【问题描述】:

我们需要以安全的方式通过 dll 边界返回一个 C 字符串!我们该怎么做?

我的想法:

extern "C" __declspec(dllexport) const char *const Api
{
    ...
    static const char *output = result.c_str();
    return output;
}

【问题讨论】:

  • 什么是result?它也是一个static变量吗?返回这样的字符串不是问题(但我仍然建议您传递一个您复制到的参数),问题是您返回指针的变量的生命周期。

标签: c++ dll c-strings


【解决方案1】:

在您的示例代码中返回了一个指针,但它指向的内存区域可能不是常驻的。

如果结果变量 (std::string?) 在堆栈上,当函数返回时它将被销毁,返回的指针将悬空——当然不是你想要的。

执行此操作的安全方法是 strdup() 响应,但随后调用者将负责释放 C 字符串。卸载 DLL 意味着返回的指针将悬空,除非它指向堆变量。

【讨论】:

    【解决方案2】:

    最简单的安全方法是

    extern "C"
    __declspec(dllexport) 
    size_t Api
        (char* dest,
         size_t dest_size)
    {
      if (dest) 
        strncpy(dest, str, dest_size);
      return strlen(str);
    }
    

    另一种安全的方法是

    extern "C"
    __declspec(dllexport) 
    void Api
        (void (*callback)(const char*))
    {
       callback(str);
    }
    

    返回 malloc'd/new'd 内存不是 100% 安全的,因为 DLL 和主程序可以链接到不同的运行时并使用不同的堆。如果是这种情况,调用者只能通过调用 DLL 中的 free/delete 来释放/删除内存(并且 DLL 必须包装这些并导出包装器)。这很麻烦。

    返回静态内存不是 100% 安全的,因为调用者可能会存储指针并卸载 DLL,在这种情况下指针会悬空。

    返回自动记忆当然是 100% 不安全的。

    【讨论】:

      猜你喜欢
      • 2020-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-26
      • 2019-05-14
      • 2017-07-15
      • 1970-01-01
      • 2018-09-11
      相关资源
      最近更新 更多