C++11 error: unable to find string literal operator 'operator"

一个简单的宏

#define LOG_INFORMATION(x, ...) LOG_ME("%s:%d, "x, __FUNCTION__,__LINE__, ##__VA_ARGS__)

一直都可以正常编译,但是当启用C++11的时候,报告编译错误

error: unable to find string literal operator 'operator""x'

网上搜了一下,说是C++11要求,当字符串跟变量连接的时候,必须增加一个空格才行。因此简单修改如下即可。

#if __cplusplus < 201103L
#define LOG_INFORMATION(x, ...) LOG_ME("%s:%d, "x, __FUNCTION__,__LINE__, ##__VA_ARGS__)
#else
#define LOG_INFORMATION(x, ...) LOG_ME("%s:%d, " x, __FUNCTION__,__LINE__, ##__VA_ARGS__)
#endif

注意:在“android-ndk-r10e”中使用的GCC版本,GCC-4.9之前的版本都存在"__cplusplus"宏定义错误的问题,需要参考“NDK下GCC定义__cplusplus不正确的问题”,把GCC升级到4.9

fatal error C1189: #error : The C++ Standard Library forbids macroizing keywords. Enable warning C4005 to find the forbidden macro.

最近在使用 VS2015 编译以前用VS2008的项目的时候,提示错误:fatal error C1189: #error :  The C++ Standard Library forbids macroizing keywords. Enable warning C4005 to find the forbidden macro.

解决方法:在项目的“预处理器定义”中增加 "_XKEYCHECK_H"

warning C4743: “const std::ios_base::failure::`vftable'”有不同的大小: 16 和 12 字节

最近在使用VS2013进行静态库链接的时候,发现在最后链接的时候,编译器报告如下警告

4>LINK : warning C4743: “const std::system_error::`vftable'”在“aaa.cc”和“bbb.cpp”中具有不同的大小:  16 和 12 字节
4>LINK : warning C4743: “const std::_System_error::`vftable'”在“ccc.cc”和“ddd.cpp”中具有不同的大小:  16 和 12 字节
4>LINK : warning C4743: “const std::ios_base::failure::`vftable'”在“eee.cc”和“fff.cpp”中具有不同的大小:  16 和 12 字节
4>LINK : warning C4743: “const std::runtime_error::`vftable'”在“xxx.cc”和“yyy.cpp”中具有不同的大小:  16 和 12 字节

尽管这个是个警告,但是由于涉及到vftable 的问题,这个问题会导致对象指针之间相互赋值的时候导致内存布局混乱,非常可能导致严重的问题。因此这个警告的危险级别甚至比错误的还要严重,绝不能简单的忽略这个问题。

研究了很久,发现,在Debug版本上面是没有问题的,但是Release版本上面必然出现该问题。并且当设置VC++ 的 “工程属性->配置属性->C/C++->优化->全程序优化”为 “否”的时候,也是可以无警告链接通过的。但是却会导致我们的工程损失更多的优化,降低运行效率。

这个问题产生的原因是一个宏引起的,这个宏就是 “_HAS_EXCEPTIONS=0” 。这个宏控制了STL对于异常的处理流程,影响着typeinfo,system_error 等几个文件中对于VC 运行时库的链接选择,要么链接libcmt.lib,要么链接msvcrt.lib。比较不凑巧的是,微软在实现这两个库的时候,其中一个比另外一个多了一个虚函数。(这种情况不应该发生,但是确实发生了!)

因此,如果我们的LIB工程定义了“_HAS_EXCEPTIONS=0” ,那么所有使用我们这个LIB的项目,都要定义这个宏。

对于简单的项目,只要都定义“_HAS_EXCEPTIONS=0” 就可以解决问题。但是对于复杂的工程,尤其是依赖了大量的第三方的已经编译过的,没有源代码的LIB项目来说,只能是采用妥协的办法,所有的工程都取消这个宏的定义,使得两者的内存布局相同。毕竟,稳定性是第一需求。