为什么MSVC编译器不检测std :: array超出绑定的访问

时间:2016-11-14 08:56:11

标签: c++ arrays

我用std::array替换了一个旧样式数组,但后来我意识到编译器(至少是MSVC)正在进行较少的绑定检查。请考虑以下代码:

double myArray[10];
myArray[11] = 3.0;

std::array<double,10> myStdArray;
myStdArray[11] = 3.0;

Fo myArray,报告了一条警告:

  

警告C4789:大小为80字节的缓冲区'myArray'将被溢出;从偏移量88

开始写入8个字节

对于myStdArray,根本没有报告任何警告。

它是编译器中的“错误”还是实现std::array的方式不允许报告此类警告?如果是这样,是否值得使用std::array似乎不太安全......

2 个答案:

答案 0 :(得分:7)

如果您的访问超出范围,您可以使用std::get来获得有保证的错误。当然,必须在编译时知道索引。

std::array<double,10> myStdArray;
std::get<9>(myStdArray) = 3.0; // ok
std::get<11>(myStdArray) = 3.0; // error

关于你问题的另一部分:这可能是我的猜想,但应该考虑标准库&#34;魔法&#34;在编译器知道其合同的方式中,没有任何东西使其无法进行事实检查。

以下示例很容易证明这一点。 clang和gcc都忽略memset调用,支持直接写入以下函数:

void zero_int(int* ptr)
{
  memset(ptr, 0, sizeof(int));
}

compiler explorer

所以,据我所知,除了潜在的实施难度/成本之外,没有什么能阻止编译器在代码中发出警告。

答案 1 :(得分:7)

myArray[11]是语言内置功能,编译器知道这些功能以及编译器可以警告的功能。

myStdArray[11]myStdArray.operator[](11)的缩写,11是一个函数调用,其中operator[]在参数类型的范围内。警告这需要查看myStdArray.operator[](11)的函数体,这通常只有在函数内联时才会发生。

此外,供应商扩展程序可能会使var orderSchema = mongoose.Schema({ user :{ type : Schema.Types.ObjectId, ref: "User" }, name : { type : String }, phone : { type : String }, residence : { type : String }, street :{ type : String }, building :{ type : String }, status :{ type : String }, paymentMode :{ type : String }, cart :{ type : Object } }); 定义明确,例如在调试模式下中止程序,在这种实现中,非常很难得到有用的编译时警告。

但是,通过此类扩展,增加的运行时安全性仍可能超过编译时警告的缺失。