对于实际问题,请跳至问题部分。有关未定义行为的有趣真实示例,请继续阅读:)
有这样的枚举:
struct EnumStruct
{
enum Enum
{
val0 = 0,
val1,
val2,
val3,
val4
};
};
在某些功能中,我们有这个:
const int arrayCount = 6;
int arr[] = {
EnumStruct::val0,
EnumStruct::val1,
EnumStruct::val2,
EnumStruct::val3,
EnumStruct::val4
InvalidValue
};
然后有一个循环将arrayCount
元素arr
放入文件中。这是Prepare()
单元测试的例程。并且单元测试应该检查InvalidValue
文件中是否存在。我被分配了一个缺陷,指出单元测试失败。不过,它在我的机器上运行完美。经过几个小时的调试后,我注意到它InvalidValue
实际上是#define
d as -1
,并且后面缺少逗号val4
。您只能想象在编写该代码的人的地址中从我口中说出的脏话(实际上,它完美运行了 3 年多)。
现在,如您所见,数组实际上由 5 个值组成 -0, 1, 2, 3, 3
但循环还将第 6 个元素写入文件,这当然是未定义的行为。现在,虽然从技术上讲它是未定义的,但在使用 MSVC 的 Windows 上不会发生崩溃 - 它只是写入该内存位置的垃圾。问题是,如果垃圾恰好不是0, 1, 2, 3, or 4
,则单元测试将成功。
问题.vcproj
: UT 的文件似乎在我不知道他们是怎么做到的,但是他们的构建越界数组元素总是 0。在我看来,整个虚拟内存在程序执行之前设置为 0。那是什么项目设置?还是我在想象事情?我的意思是,如果只是运气好,有一个 0 超出了数组的范围,那么在多次执行时我的运气就会失败,不是吗?但它总是 0 ......我很困惑。顺便说一句,当我构建同一个项目时,越界元素在每次执行时总是具有不同的值。你能解释一下吗?谢谢。