昨天尝试把自己的自定义DLL版本发布成Release,我的项目中有一个控制台程序,该程序中引用了两个自定义的DLL,在DEBUG模式下程序运行正常,但发布成Release版本后一经运行就马上出现异常。
这类问题很常见,因此我也从网上搜了很多关于Debug版本与Release版本之间的区别,但按照找到的方法多次尝试都解决不了问题,最后我尝试消除所有编译警告,看能不能解决问题。在我的警告中出现最多的就是以下这条:
Warning 1 warning C4251: 'ZacharyHash::BucketNode::_value' : class 'std::basic_string<_Elem,_Traits,_Ax>' needs to have dll-interface to be used by clients of class 'ZacharyHash::BucketNode' e:\c&c++ study projects\algorithms\hash\hashlib\BucketNode.h 27 1 HashLib
而这条警告源于这个自定义类型:
{
public :
BucketNode( void );
~ BucketNode( void );
string _value;
BucketNode * _next;
};
因为这个类是链式地址Hash表的一个内部使用的类型,因此我没有为它的字段设置getter和setter,因为那显得低效,直接就把它的数据列为公共字段。但是因为一时疏忽,竟然也把这个类型定义为DLL的输出类型(HASHLIB_API),于是编译器就提示,如果要把这个类型作为DLL输出,那应该把它公共成员中涉及的类型也声明为DLL输出(在这里就是string类型),否则就会引起错误。那为什么这个信息会作为一个警告信息提示,而非编译错误呢?原因可能就在于外部引用DLL的人不一定会使用到这个公共成员(也就是_value),但一定引用了,那就会出现异常。
不过这里我有两个疑问还没解决,希望看到这篇文章的朋友能指点一下。第一:为什么string类型这种标准库类型也需要人为地声明为DLL导出类型?如果要声明该怎么声明?第二:为什么在DEBUG模式下,这种错误不会对程序运行产生引用?
最后当我把所有DLL输出标识符撤走以后,重新编译,用新生成的DLL替换回原来的DLL,在Release版本下就可以正常运行程序了。