首页 > 解决方案 > 标准向量内存分配 linux vs windows 编译器

问题描述

一个非常简单的程序,用于测试 Linux 上的英特尔编译器(英特尔 18.0)和 Windows 上的 Visual c++(MSVC 2015)之间的 STL 实现。

  1. 首先,如何使 linux 像 windows 一样致命/崩溃(因为我有一个巨大的代码库)。从技术上讲,我期待来自 linux 的信号 11,无论我测试的向量大小如何,每次都不会抛出垃圾值。

  2. 有人可以解释一下幕后发生的事情(内存分配明智及其规则,以及它是否依赖于实现/平台/编译器)。?只是为了我的理解。

'

#include "iostream"
#include "vector"
using namespace std;
int main(int argc,char* argv[])
{   
   vector<int> v;
   //v.resize(5);  (my bad, please ignore this, i was testing and posted incorrect version)
   cout<<"Initial vector size: "<<v.size()<<endl;
   for(int i=1;i<=5;++i)
   {
       v.push_back(i);
   }
   cout<<"size of vector after: "<<v.size()<<endl;

   for(int j=5;j>=0;--j) // Notice my upper bound.
   {
      cout<< "printing " <<v[j]<<std::endl;
   }
   return 0;
}

正如预期的那样,两者都没有编译问题。随后,Windows 崩溃并显示一个很好的消息“向量下标超出范围”,而 linux 每次都抛出一些垃圾值并继续。

标签: c++linuxvisual-c++vectorstl

解决方案


假设你打错v.resize(5)了,这里有一些答案:

如何使 linux 像 windows 一样致命/崩溃(因为我有一个巨大的代码库)。

使用std::vector::at()它来验证索引并按设计抛出异常。std::vector::operator[]不假设验证索引,即使某些平台为某些配置执行此操作(看起来调试中的 Windows 编译器具有此类验证),您也不能在任何地方都要求它。

从技术上讲,我期待来自 linux 的信号 11,无论我测试的向量的大小如何,每次都不会抛出垃圾值。

这是您期望的问题。给出无效索引会std::vector::operator[]导致未定义的行为,并且您不能指望它会给出信号 11 或其他特定的东西。

财政年度:

std::vector::operator[]

返回对指定位置 pos 的元素的引用。不执行边界检查

标准::向量::at()

如果 pos 不在容器的范围内,则抛出 std::out_of_range 类型的异常。

重点是我的。

至于内存分配,它是特定于实现的,它们中的大多数不会为 5 个元素分配内存,而是提前分配内存,以提高效率,这就是为什么你在 Linux 上的代码没有崩溃,而是在你读取值时产生垃圾来自未初始化的内存。但这可能随时改变,你不应该以任何方式依赖这种行为。


推荐阅读