Today we found a bug at work, which can be simplified to this:
今天我们发现了一个工作中的错误,可以简化为:
std::map<int, Obj*> workMap;
for(auto a : workMap)
{
workMap.erase(a.first);
}
Actually, we invoked function, that invoked function that did erase, but it is not the point.
实际上,我们调用了函数,调用了擦除的函数,但它不是重点。
The point is, that on my computer with visual studio compiler I've got list iterator is not incrementable error, while my colleague with mingw has got no errors at all!
关键是,在我的计算机上使用visual studio编译器我有列表迭代器不是可递增的错误,而我的同事mingw完全没有错误!
I understand, that we have different compilers and different implementations of STL(probably). It is normal, that they could have different warnings or flags to suppress warnings. But it is different runtime error behaviour. Is this normal? And can I somehow "enable" all runtime errors?
我明白,我们有不同的编译器和不同的STL实现(可能)。通常情况下,他们可以使用不同的警告或标志来禁止警告。但它是不同的运行时错误行为。这是正常的吗?我可以以某种方式“启用”所有运行时错误吗?
2 个解决方案
#1
4
These types of for-loops are not for changing the container itself. You invalidate iterators you still use, thus anything can happen. Since this is undefined behavior, the compiler is allowed to generate code that does anything, there are no guarantees what so ever, so both compilers are correct.
这些类型的for循环不用于更改容器本身。您使仍然使用的迭代器无效,因此可能发生任何事情。由于这是未定义的行为,因此允许编译器生成执行任何操作的代码,但不能保证这样做,因此两个编译器都是正确的。
Your observation is caused by the fact that msvc enables some runtime checking for debug builds by default, gcc does not.
您的观察是由于msvc默认启用了一些运行时检查调试版本,而gcc没有。
You can enable runtime checking for libstd++
, the standard library implementation of gcc, with -D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
during compilation. It will show an error in your example. (Live)
您可以在编译期间使用-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC为libstd ++(gcc的标准库实现)启用运行时检查。它会在您的示例中显示错误。 (生活)
#2
2
Just so we're all clear, this code:
我们都清楚了,这段代码:
std::map<int, Obj*> workMap
for(auto a : workMap)
workMap.erase(a.first);
causes undefined behavior and should not be expected to work properly.
导致未定义的行为,不应该期望正常工作。
Visual Studio is simply being helpful and providing a runtime error about this. It's not obligated to do this.
Visual Studio只是很有帮助,并提供有关此的运行时错误。它没有义务这样做。
#1
4
These types of for-loops are not for changing the container itself. You invalidate iterators you still use, thus anything can happen. Since this is undefined behavior, the compiler is allowed to generate code that does anything, there are no guarantees what so ever, so both compilers are correct.
这些类型的for循环不用于更改容器本身。您使仍然使用的迭代器无效,因此可能发生任何事情。由于这是未定义的行为,因此允许编译器生成执行任何操作的代码,但不能保证这样做,因此两个编译器都是正确的。
Your observation is caused by the fact that msvc enables some runtime checking for debug builds by default, gcc does not.
您的观察是由于msvc默认启用了一些运行时检查调试版本,而gcc没有。
You can enable runtime checking for libstd++
, the standard library implementation of gcc, with -D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
during compilation. It will show an error in your example. (Live)
您可以在编译期间使用-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC为libstd ++(gcc的标准库实现)启用运行时检查。它会在您的示例中显示错误。 (生活)
#2
2
Just so we're all clear, this code:
我们都清楚了,这段代码:
std::map<int, Obj*> workMap
for(auto a : workMap)
workMap.erase(a.first);
causes undefined behavior and should not be expected to work properly.
导致未定义的行为,不应该期望正常工作。
Visual Studio is simply being helpful and providing a runtime error about this. It's not obligated to do this.
Visual Studio只是很有帮助,并提供有关此的运行时错误。它没有义务这样做。