size_t算术,负值

时间:2018-03-27 20:20:36

标签: c++ string

我被要求在作业中复制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中,9tam_,例如假设开始为1010 < 9 + 18446744073709551615 10 < 9 + (-1)

我期待:

length + 1

这样就抛出了异常,但实际上我得到了

new[]

哪个是假的,不会抛出异常。随着函数的继续,它会为大小size_t分配一个char数组,由于18446744073709551615Workbooks.Open Filename:= "C:\file2"视为应该Dim wk as Workbook, sh as worksheet, path as string path = "C:\file2" Set wk = Workbooks.Open(path) Set sh = ActiveSheet 'etc... ,系统会拒绝该数组,ThisWorkbook这会导致程序崩溃。

我想知道为什么我的预期结果不正确。

1 个答案:

答案 0 :(得分:2)

难以检查溢出和下溢问题。通常,您需要在进行算术之前进行检查,而不是之后进行检查。

首先,让我们清楚发生了什么。

// The call
foo.substr(9, -1);

-1int,但该函数需要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。