我的 mac 笔记本电脑有 4 GB 1600 MHz DDR3 内存。
在经典的 MemoryBlock 类中,
class MemoryBlock
{
public:
// Default constructor
explicit MemoryBlock(): _length{0}, _data{nullptr} {}
explicit MemoryBlock(const int l): _length{l}, _data{new int[l]} {}
// Big-Five (blahblah)
// --------
int length() const
{
return _length;
}
private:
int _length;
int* _data;
};
然后我试着看看在像这样溢出之后会发生什么,将 x
从 1e9
更改为 1e10
到 1e11
.
MemoryBlock x(100000000000);
Info<< "x's length = " << x.length() << endl;
这给了我(用 g++-6
和 cmake
编译),
[LOG] x( 1000000000)'s length = 1000000000
[LOG] x( 10000000000)'s length = 1410065408
[LOG] x( 100000000000)'s length = 1215752192
警告是这样的,
warning: overflow in implicit constant conversion [-Woverflow]
MemoryBlock x(100000000000);
当使用 size_t
作为 _length
类型时,我将看不到这个警告,不知道为什么。
无论如何,我的问题是,1410065408
和1215752192
是如何生成的?谢谢
最佳答案
1215752192
是 100000000000 % 2^32
的结果,其中 2^32
是 32 位整数的最大可表示值(这是大多数平台上 int
的大小)。注意 signed overflow is undefined behavior !
使用 std::size_t
似乎是:
将可表示范围增加到无符号 64 位(在您的特定平台上,因为它是 implementation defined),这样您的
100000000000
就不会溢出,并且行为将被定义......或将可表示范围增加到无符号 32 位,其中
100000000000
溢出 (但以明确定义的方式)。
确定前面声明的唯一方法是验证 sizeof(int)
和 sizeof(std::size_t)
在您的机器上的计算结果,并且找出代码中发生的确切溢出。
如果你想保证一个特定的整数有特定的位数,你应该查看"Fixed width integer types" .
cppreference/Fundamental types有一个很好的表,其中包含 C++ 基本类型的最常见范围。
以后还可以用-fsanitize=undefined
捕捉类似的签名溢出问题。
关于c++ - 内存块类在溢出后给出一个数字,为什么以及如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41486094/