ATL的另一个陷阱

ATL早期提供了宏A2W,W2A进行编码转换,但是该组宏存在以下缺点:

1、默认认为转换前的参数(A2W)、转换后的结果(W2A)的编码是ANSI;

2、转换后结果保存在栈上。

 

该组宏无法满足我们从UTF8、UCS2之间的互相转换,并且有可能导致栈溢出。鉴于此,当我发现可以用CA2W/CW2A这两组宏进行转码时,内心欢喜。该组宏的构造函数可以指定代码页,同时转换后的结果保存在堆上。查看源码可知,该组宏内部是通过这两个API实现转码的:

WideCharToMultiByte,MultiByteToWideChar。这两个API在调用时必须指定结果缓冲区的长度,因此,正常的做法是调用两次API。第一次调用获取所需长度,第二次调用进行真正的转码。但是CA2W/CW2A只调用了一次,在调用前预测结果缓冲区的长度。对于CA2W,结果缓冲区的长度等于输入参数的长度;对于CW2A,结果缓冲区的长度等于输入参数的长度的两倍。由于UCS2编码的字符串的字符数,必然小于其他编码的字符串的字节数,所以CA2W分配的缓冲区足够大,调用MultiByteToWideChar必然成功。然而,CW2A内部预测的缓冲区长度只在目标字符串的编码为ANSI时才成立。对于UTF8编码的目标字符串,其字符数有可能等于输入长度的3倍、6倍。针对这种情况,CW2A对WideCharToMultiByte的调用可能由于缓冲区长度不足而失败,从而导致ATL抛出异常。

 

所以,大家使用CW2A进行字符编码转换时,切记:目标编码的字符串长度必须小于输入参数的2倍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值