编译报错Assumed value of MB_LEN_MAX wrong的排查与解决求助
我在Ubuntu 16.04系统上使用g++ 6.4.0编译一款图像分割程序时,遇到了和你完全一样的编译错误。执行make命令(实际编译指令为:
g++ -g -O3 -I. -o segment segment.cpp -lm
)时,报错信息如下:
In file included from /usr/include/wchar.h:887:0, from /usr/include/c++/6/cwchar:44, from /usr/include/c++/6/bits/postypes.h:40, from /usr/include/c++/6/iosfwd:40, from /usr/include/c++/6/ios:38, from /usr/include/c++/6/istream:38, from /usr/include/c++/6/fstream:38, from ./pnmfile.h:27, from segment.cpp:23: /usr/include/x86_64-linux-gnu/bits/wchar2.h:448:3: error: #error "Assumed value of MB_LEN_MAX wrong" # error "Assumed value of MB_LEN_MAX wrong" ^~~~~ Makefile:14: recipe for target 'segment' failed make: *** [segment] Error 1
错误原因分析
从wchar2.h的代码片段可以看出,这个头文件自己定义了__WCHAR_MB_LEN_MAX 16,然后检查系统中已定义的MB_LEN_MAX是否和这个值相等,如果不等就抛出错误:
#define __WCHAR_MB_LEN_MAX 16 #if defined MB_LEN_MAX && MB_LEN_MAX != __WCHAR_MB_LEN_MAX # error "Assumed value of MB_LEN_MAX wrong" #endif
问题出在头文件的包含顺序上:pnmfile.h先包含了<climits>(这个头文件会定义MB_LEN_MAX),之后再包含<fstream>,而<fstream>的依赖链最终会引入wchar2.h,此时MB_LEN_MAX已经被定义,且和__WCHAR_MB_LEN_MAX 16不匹配,触发了错误。
你单独测试<fstream>的代码能成功,是因为那段代码没有同时包含<climits>,所以不会触发这个宏检查冲突。
修复方案
这里有几个安全可靠的修复方法,按推荐优先级排序:
方法1:调整pnmfile.h的头文件包含顺序
把<fstream>的包含语句移到<climits>之前,这样在引入wchar2.h时,MB_LEN_MAX还没被定义,wchar2.h就会使用自己的__WCHAR_MB_LEN_MAX值,不会触发检查。修改后的pnmfile.h相关代码:
#include <cstdlib> #include <fstream> // 移到<climits>之前 #include <climits> #include <cstring> #include "image.h" #include "misc.h"
方法2:编译时手动指定MB_LEN_MAX的值
修改Makefile中的编译指令,添加-DMB_LEN_MAX=16,强制让编译器使用wchar2.h期望的值:
g++ -g -O3 -I. -DMB_LEN_MAX=16 -o segment segment.cpp -lm
如果是直接修改Makefile,找到对应编译行,添加这个编译选项即可。
方法3:不推荐——修改系统头文件(谨慎操作)
你可以先通过以下命令查看系统当前的MB_LEN_MAX值:
grep MB_LEN_MAX /usr/include/limits.h
如果确实不是16,修改wchar2.h中的__WCHAR_MB_LEN_MAX为系统实际值,但这种方法会影响系统中其他依赖这个头文件的程序,所以非常不推荐。
我自己用方法1修复后,程序顺利编译通过了,你可以试试!
内容的提问来源于stack exchange,提问作者Thomas Cohn

