朴素的反向字符串迭代无限循环 and/or 断言失败 C++ / Visual Studio 2022
Naive reverse string iteration infinite loop and/or assertion failure C++ / Visual Studio 2022
我正在尝试对字符串进行反向迭代,但在最新的 VS 中遇到 [] 运算符的断言失败。
int foo() {
std::string s = "s";
for (int i = (s.size() - 1); i >= 0; i--) {
std::cout << s[i] << std::endl;
}
return 0;
}
注释掉cout行给出无限循环警告,确实进入无限循环:
int foo2() {
std::string s = "s";
for (int i = (s.size() - 1); i >= 0; i--) {
//std::cout << s[i] << std::endl;
}
return 0;
}
无论是否在 for 循环中有任何内容,向前迭代都可以正常工作:
int bar() {
std::string s = "s";
for (int i = 0; i < s.size(); i++) {
std::cout << s[i] << std::endl;
}
return 0;
}
我使用的是 C++14 标准和用于其他 compilers/older 版本 VS 的相同代码。任何字符串大小都存在相同的问题(尽管这应该无关紧要)。我知道我可以修改代码以使用和取消引用指针而不是使用 int,但想了解为什么这不再起作用,为什么它不安全或不正确,或者我还缺少什么。谢谢!
Commenting out the cout line gives infinite loop warning and indeed enters infinite loop
s.size()
是一个 unsigned long
,因此它永远不会小于 0
。由于将 unsigned long
分配给 int
而缩小转换的行为是实现定义的行为,尽管将 unsigned long
值 0 分配给 int
时应该不是问题,至少我不这么认为,但谁知道呢,MSVC 确实有它的怪癖。
编译器似乎足够聪明,可以预测当 for
循环的这个特定主体存在时不会有无限循环,这让我相信访问时可能会抛出异常数组,可能越界访问。
使用调试器跟踪 i
的值是了解正在发生的事情的最佳选择。
会不会是您的 int 默认为无符号,因此在 i=0 时递减以得到高值?
正如@PeteBecker 提到的,int 应该被签名并且不应该溢出。但是我的猜测是您的实际代码不使用 int.
这个问题实际上最初是由“auto”i 而不是“int”i 引起的,但没有正确刷新。 Auto 给了我一个 unsigned int 类型,它溢出 [] 运算符,或者一旦 i = 0 循环完成并执行 i-- 就会导致无限循环从零翻转到 18446744073709551615。
谢谢大家的热心回复!
我正在尝试对字符串进行反向迭代,但在最新的 VS 中遇到 [] 运算符的断言失败。
int foo() {
std::string s = "s";
for (int i = (s.size() - 1); i >= 0; i--) {
std::cout << s[i] << std::endl;
}
return 0;
}
注释掉cout行给出无限循环警告,确实进入无限循环:
int foo2() {
std::string s = "s";
for (int i = (s.size() - 1); i >= 0; i--) {
//std::cout << s[i] << std::endl;
}
return 0;
}
无论是否在 for 循环中有任何内容,向前迭代都可以正常工作:
int bar() {
std::string s = "s";
for (int i = 0; i < s.size(); i++) {
std::cout << s[i] << std::endl;
}
return 0;
}
我使用的是 C++14 标准和用于其他 compilers/older 版本 VS 的相同代码。任何字符串大小都存在相同的问题(尽管这应该无关紧要)。我知道我可以修改代码以使用和取消引用指针而不是使用 int,但想了解为什么这不再起作用,为什么它不安全或不正确,或者我还缺少什么。谢谢!
Commenting out the cout line gives infinite loop warning and indeed enters infinite loop
s.size()
是一个 unsigned long
,因此它永远不会小于 0
。由于将 unsigned long
分配给 int
而缩小转换的行为是实现定义的行为,尽管将 unsigned long
值 0 分配给 int
时应该不是问题,至少我不这么认为,但谁知道呢,MSVC 确实有它的怪癖。
编译器似乎足够聪明,可以预测当 for
循环的这个特定主体存在时不会有无限循环,这让我相信访问时可能会抛出异常数组,可能越界访问。
使用调试器跟踪 i
的值是了解正在发生的事情的最佳选择。
会不会是您的 int 默认为无符号,因此在 i=0 时递减以得到高值?
正如@PeteBecker 提到的,int 应该被签名并且不应该溢出。但是我的猜测是您的实际代码不使用 int.
这个问题实际上最初是由“auto”i 而不是“int”i 引起的,但没有正确刷新。 Auto 给了我一个 unsigned int 类型,它溢出 [] 运算符,或者一旦 i = 0 循环完成并执行 i-- 就会导致无限循环从零翻转到 18446744073709551615。
谢谢大家的热心回复!