(如何)处理C++代码中可能的整数溢出?

Fre*_*abe 6 c++ overflow

时不时地,特别是当做一些代码库的64位构建时,我注意到有很多情况下整数溢出是可能的.最常见的情况是我做这样的事情:

// Creates a QPixmap out of some block of data; this function comes from library A
QPixmap createFromData( const char *data, unsigned int len );

const std::vector<char> buf = createScreenShot();
return createFromData( &buf[0], buf.size() ); // <-- warning here in 64bit builds
Run Code Online (Sandbox Code Playgroud)

问题是std::vector::size()很好地返回一个size_t(在64位构建中是8个字节)但是该函数恰好采用了unsigned int(在64位构建中仍然只有4个字节).所以编译器会正确警告.

如果可能的话,我会尝试修复签名,以便首先使用正确的类型.但是,当我组合来自不同库的函数时,我经常遇到这个问题,我无法修改.不幸的是,我常常采取一些推理:"好吧,没有人会做截图生成超过4GB的数据,所以为什么要打扰"并且只需更改代码即可

return createFromData( &buf[0], static_cast<unsigned int>( buf.size() ) );
Run Code Online (Sandbox Code Playgroud)

这样编译器就会关闭.然而,这感觉真的很邪恶.所以我一直在考虑使用某种运行时断言,这至少会在调试版本中产生一个很好的错误,如:

assert( buf.size() < std::numeric_limits<unsigned int>::maximum() );
Run Code Online (Sandbox Code Playgroud)

这是一个有点漂亮了,但我想知道:你是怎么处理这种问题,那就是:整数溢出这是"几乎"不可能(实际上).我想这意味着它们不适合你,它们不会出现在QA中 - 但它们会在客户面前爆炸.

Ste*_*sop 4

如果您无法修复类型(因为您无法破坏库兼容性),并且您“确信”大小永远不会变得那么大,那么您可以boost::numeric_cast使用static_cast. 如果值太大,这将引发异常。

当然,周围的代码必须做一些模糊合理的例外 - 因为这是一个“预计不会发生”的情况,这可能只是意味着彻底关闭。仍然比继续使用错误的尺寸要好。