size_t负值的算术
size_t arithmetic with negative value
本文关键字:size 更新时间:2023-10-16
我被要求在作业中复制std::string
,我在实现substr
函数时遇到问题。在老师给我们的一组测试中,有一个测试的length
等于-1
。substr
的矿山申报是:
Cadena substr(size_t start, size_t length) const;
我(认为)size_t
会阻止传递负值。问题是在定义中我检查size() < start + length
(假设tam_
与size()
相同):
if (tam_ < start + length)
throw std::out_of_range("Error");
在我的系统中,-1
unsigned
是18446744073709551615
,因此,例如假设 start 是9
,tam_
是10
。
我期待:
10 < 9 + 18446744073709551615
所以抛出异常,但实际上我得到
10 < 9 + (-1)
这是假的,不会抛出异常。随着函数的继续,它会为大小分配一个 char 数组length + 1
,系统拒绝了该数组,因为new[]
将size_t
视为应有的18446744073709551615
,它是如此之大以至于导致程序崩溃。
我想知道为什么我的预期结果不正确。
溢出和下溢问题很难检查。 一般来说,您需要在进行算术之前进行检查,而不是之后。
首先,让我们弄清楚发生了什么。
// The call
foo.substr(9, -1);
-1
是一个int
,但函数需要std::size_t
所以-1
被转换,你得到真正的大数(RBN)。
然后,测试:
size() < start + length
这些是无符号类型,因此如果算术(即加法)超过可以表示的范围的上限或下限,则该值将环绕。 (对于有符号类型,行为将是未定义的。
在这里,length
是RBN。 当您添加start
和 RBN 时,添加将换行为一个小数字。 您错过了溢出检测。
要修复它,您需要检查两件事:(1)start
是否在边界内,(2)start
后字符串的其余部分是否比length
长。
if (start > size() || size() - start < length)
throw std::::out_of_range("Error");
步骤 (1) 是关键,因为它保证步骤 (2) 中的减法不会低于 0。
相关文章:
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 大于65535的C++数组[size]引发不一致的溢出
- 为什么(-1)%vector::size()总是返回0
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 循环中的条件:为什么每次都调用strlen(),而vector.size()只调用一次
- 为什么这个 std::queue/指向结构的指针列表直到 List.Size() == 0 才释放内存?
- 在函数中使用 const int size 参数创建数组会在 Visual Studio 中抛出错误 C++:表达式的计
- vector.size() 在比较中意外工作
- vector.back() 和 vector[vector.size() - 1] 之间的区别?
- 返回 str vs. str.substr(0,str.size()) 在 leetcode 中给了我不同的输出
- 为什么 GCC 不能假设 std::vector::size 在这个循环中不会改变?
- 为什么"(!v.empty())"比"(v.size() >0)"好?
- 迭代器库中的 std::size() 不适用于传递给函数的 C 样式数组
- std::string.size() 未知行为
- 为什么gmp会在这里与"invalid next size"重新定位一起崩溃?
- 为什么我会"Invalid read of size 8"?(瓦尔格林德)
- 从 std::string 到 std::array<char,size> 的 memcopy 额外数据是否是一种未定义的行为?
- 使用 std::size 来自非 const 上下文
- "fast"或"normal"在"free(): invalid next size (fast)"中是什么意思?
- 行 - " vector<int> used(adj.size(), 0); "是什么意思?