log4cxx中文输出错误补丁
(金庆的专栏)
已提交Bug:https://issues.apache.org/jira/browse/LOGCXX-399
log4cxx_0.10.0及主干代码,Windows下输出中文,发现有多余输出。
void main()
{
setlocale(LC_ALL, "");
LOG4CXX_INFO(pLog, "一二"); // log 2 chinese characters.
}
输出为:一二二。
错误在 MbstowcsCharsetDecoder::decode().
size_t converted = mbsrtowcs(...
if (converted == (size_t) -1) {
...
} else {
stat = append(out, buf);
in.position(in.position() + converted); // ERROR!
}
mbsrtowcs()返回的是汉字的字数,而输入缓冲区in的position是按字节计数的,
对于汉字,position应该增加2*converted,而不是converted.
因为position少增加了一半,所以后半部分字符串会重复解码。
可如下更改:
if (converted == (size_t) -1) {
...
} else {
stat = append(out, buf);
// in.position(in.position() + converted); // ERROR!
if (src)
in.position(src - in.data());
else // mbsrtowcs() set src to NULL.
in.position(in.position() + strnlen(in.current(), in.remaining()));
}
此处的in是个二进制块,其中可能会有0,而mbsrtowcs()的输入应该是0结尾的字符串。
碰到0时,mbsrtowcs()认为已经成功转换到串尾,并将src重设为NULL。
代码中已经有对0的处理。
有可能mbsrtowcs()会越过输入缓冲区的尾部一直读取,最多为256字节,仍有可能出现垃圾字符。
但是现在的std::string实现有0结尾,所有才没有出错。若要更正这个错误,就需要在输入缓冲区尾部添0。