c++ - 数组越界元素的值——它应该在每次执行时改变还是保持不变?

标签 c++ visual-studio visual-studio-2008 undefined-behavior project-properties

对于实际问题,跳转到问题部分。有关未定义行为的有趣真实示例,请继续阅读 :)

有这个枚举:

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
      };    

然后有一个循环将 arrarrayCount 元素放入文件中。这是单元测试的 Prepare() 例程。并且单元测试应该检查文件中是否存在 InvalidValue。我被分配了一个缺陷,说明单元测试失败。不过它在我的机器上运行完美。经过几个小时的调试,我注意到 InvalidValue 实际上是 #defined as -1,并且 后缺少一个逗号>val4。您只能想象在写该代码的人的地址中从我嘴里说出的脏话(实际上,它完美运行了 3 年多)。

现在,如您所见,该数组实际上由 5 个值组成 - 0, 1, 2, 3, 3 但循环还将第 6 个元素写入文件,即当然是未定义的行为。现在,虽然从技术上讲它 未定义,但在使用 MSVC 的 Windows 上不会发生崩溃 - 它只是写入该内存位置的垃圾。问题是,如果垃圾恰好不是 0、1、2、3 或 4,单元测试就会成功。

问题:似乎 UT 的 .vcproj 文件在构建 UT 之前以某种方式进行了修补。我不知道他们是怎么做到的,但是他们的构建越界数组元素总是 0。在我看来,整个虚拟内存在程序执行之前都设置为 0。那是什么项目设置?还是我在想象事情? 我的意思是,如果 0 位于数组的边界之外只是运气,那么在多次执行时我的运气就会失败,不是吗?但它总是 0 ...我很困惑。 顺便说一下,当我构建同一个项目时,越界元素在每次执行时总是有不同的值。你能解释一下吗?谢谢。

最佳答案

真正的问题是内存在开始时总是 0 吗?好吧,这可能取决于。通常,当操作系统为您提供一页内存时,它将被清除(作为一种安全措施,这样您就无法读取任何其他进程在其内存中的值),因此在许多情况下您会发现未初始化的可以看起来 像 0,直到内存在您自己的进程中被重用,在那里您将获得您之前编写的任何内容。

还有一些编译器标志可以影响它。为了检测未初始化的内存问题,有时调试版本会在从操作系统分配内存之后和将其处理给程序之前将模式写入内存,并在重新分配之前在程序中释放内存之后写入不同的模式(以检测对释放内存的访问),所以更容易识别发生了什么(如果你在调试器中看到该值为 0xDEADBEEF,你就会知道内存已经被程序释放了。你将不得不阅读编译器/IDE 文档以获得更精确的信息。

关于c++ - 数组越界元素的值——它应该在每次执行时改变还是保持不变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6584190/

相关文章:

c++ - 为什么这段代码运行失败

c# - 在 .net 中针对来自 visual studio 测试客户端的不同机器对 WCF 进行单元和性能测试的最佳方法是什么

visual-studio-2008 - 我应该使用 VS 2008 重构支持还是购买 ReSharper?

visual-studio - Visual Studio 的 "Start Without Debugging"在 JetBrains Rider 中是否等效?

c++ - 如何将 SDK 连接到 Visual Studio?

visual-studio - TFS 2008 项目文件的状态不正确

visual-studio - Visual Studio 2008 ASMX文件

c++ - 为什么 G++ 不为不返回任何内容的模板方法生成警告?

c++ - 为什么要在 C 和 C++ 项目中创建包含/目录?

c++ - c++中分配器和内置数组的区别?