如何将C ++对象传递给具有不同_ITERATOR_DEBUG_LEVEL的DLL

时间:2011-03-17 13:40:45

标签: c++ visual-studio-2010 stl

我的可执行文件调用了许多我自己编写的DLL。根据这些DLL使用的第三方C ++库,我无法自由选择所有DLL的编译器设置。因此,在某些DLL中_ITERATOR_DEBUG_LEVEL设置为2(在调试版本中默认),但在我的可执行文件_ITERATOR_DEBUG_LEVEL中设置为0,根据严重的性能问题。

当我现在将std::string传递给DLL时,一旦DLL尝试将其复制到本地std :: string obj,应用程序就会崩溃,因为DLL中的字符串对象的内存布局与我的可执行文件中的不同。到目前为止,我通过传递C字符串来解决这个问题。我甚至编写了一个小类,它将std::map<std::string, int>转换为C-Data中的临时表示形式,以便将数据传递给DLL。这很有效。

我如何克服这个问题?我想传递更多不同的类和容器,由于多种原因,我不想使用_ITERATOR_DEBUG_LEVEL = 2.

3 个答案:

答案 0 :(得分:3)

建议不要使用带有第三方库的复杂类型(stl ...)的c ++接口,如果只将它们作为二进制文件使用,或者需要特殊的编译设置,这些设置与您的设置不同。

正如您所写 - 根据您的设置,使用相同的编译器可能会有不同的实现,并且使用不同的编译器,情况会变得更糟。

如果可能,使用编译器和设置编译第三方库。

如果不可能,您可以编写一个包装器DLL,它使用与第三方库相同的编译器和相同的设置进行编译,并为您提供C-Data接口。在你的项目中,你可以编写另一个包装类,这样你就可以使用STL-Objects进行函数调用,并在“后台”中对它们进行转换和转换。

答案 1 :(得分:2)

我对_SECURE_SCL和_ITERATOR_DEBUG_LEVEL等标志的经验是,如果你试图通过dll boudaries传递一个stl对象,它们必须是一致的。 但是我认为你可以将一个stl对象传递给一个具有较小_ITERATOR_DEBUG_LEVEL的dll 因为您可以将调试dll中实例化的stl对象提供给在发布模式下编译的dll。

编辑07/04/2011 显然,Visual Studio 2010提供了一些细节来检测ITERATOR_DEBUG_LEVEL之间的不匹配。我还没看过这个视频。

http://blogs.msdn.com/b/vcblog/archive/2011/04/05/10150198.aspx

答案 2 :(得分:2)

问题是std :: string和其他容器是模板类。它们是在编译时为每个二进制文件生成的,因此在您的情况下,它们的生成方式不同。你可以说它不是同一个物体。

要解决此问题,您有多种解决方案,但它们都遵循相同的经验法则:不要在二进制文件之间共享的标题代码中公开任何模板代码

您可以仅为此目的创建特定接口,或者只是确保您的标头不公开模板类型和功能。您可以在二进制文件中使用这些模板类型,但不要将它们公开给其他二进制文件。

接口中的std :: string可以用const char *替换。你仍然可以在你的系统中使用std :: string,只需在接口中询问const char *并使用std :: string :: c_str()来公开你的数据。

对于地图和其他容器,您必须提供允许外部代码操作内部地图的功能。比如“Find(const char * key);”。

主要问题在于您公开的类的模板成员。解决这个问题的一种方法是使用PImpl习惯用法:创建(或生成)API,标题,只显示可以对二进制文件执行的操作,然后确保API指向二进制文件中的实际对象。 API将在外部使用,但在您的库中,您可以使用您想要的任何代码进行编码。 DirectX API和其他OS API就是这样完成的。