简体   繁体   English

在GCC的“Debug”版本中绑定检查std :: array

[英]Bound checking of std::array in “Debug” version of GCC

Benefits of C++11 std::array s when programming have been explained by experts, but there is one thing I would like to get from the compiler. 专家解释了编程时C ++ 11 std::array的优点,但我希望从编译器中获得一些东西。 Ability to turn ON range check that is default when using .at() while compiling the code that uses [] . 能够打开在编译使用[]的代码时使用.at()时默认的范围检查。

It could be beneficial for checking range violations especially for multidimensional arrays because in that case it is less likely that range violation will cause segfault(because you often own memory around the inner array so [5000][-123] will still likely point to memory that you own). 检查范围违规尤其是多维数组可能是有益的,因为在这种情况下,范围违规不太可能导致segfault(因为你经常在内部数组周围拥有内存,所以[5000][-123]仍然可能指向内存你拥有的)。

So I would like to know if there is a switch that will compile into machine code that checks ranges: 所以我想知道是否有一个开关可以编译成检查范围的机器代码:

    const uint32_t dim1=10*1000,dim2=3;
    std::array<std::array<int, dim2>, dim1> test_2Darray;
    int undefined_value=test_2Darray[dim2-1][dim1-1];
    std::cout<<"ouch ("<<undefined_value<<")"<<std::endl;
    int ok_value=test_2Darray[dim1-1][dim2-1];
    std::cout<<"OK   ("<<ok_value<<")"<<std::endl;
    //  test_2Darray.at(dim2-1).at(dim1-1); -->terminate called after throwing an instance of 'std::out_of_range'
    //      what():  array::at

If you ask why I don't switch to .at() - I might need the performance, also I have a lot of code with [] already written and I'm not smart enough to smart to do replace for 1D let alone 2D arrays. 如果你问为什么我不切换到.at() - 我可能需要性能,我也有很多代码[]已经写好了,我不聪明,不能聪明地替换1D更不用说2D了阵列。

I use GCC 4.6 我使用GCC 4.6

It looks like the array that comes with gcc 4.6 doesn't have a debug mode yet. 看起来gcc 4.6附带的数组还没有调试模式。 Understandable since C++11 support is still experimental. 可以理解,因为C ++ 11支持仍然是实验性的。

There is a flag _GLIBCXX_DEBUG which is usually used to turn on debug mode. 有一个标志_GLIBCXX_DEBUG ,通常用于打开调试模式。 If you look at /usr/include/c++/4.6/debug/vector:313 you'll see operator[] has: 如果你看一下/usr/include/c++/4.6/debug/vector:313,你会看到operator[]有:

__glibcxx_check_subscript(__n);

Now, this may be uber-evil (and I mean really evil) but it looks like we can conditionally add this to array. 现在,这可能是超级邪恶(我的意思是真的很邪恶),但看起来我们可以有条件地将它添加到数组中。 Change lines 148-154 of /usr/include/c++/4.6/array from: 更改/usr/include/c++/4.6/array的第148-154行:

reference
operator[](size_type __n)
{ return _M_instance[__n]; }

const_reference
operator[](size_type __n) const
{ return _M_instance[__n]; }

to: 至:

reference
operator[](size_type __n)
{
#ifdef _GLIBCXX_DEBUG
    __glibcxx_check_subscript(__n);
#endif
    return _M_instance[__n];
}

const_reference
operator[](size_type __n) const
{
#ifdef _GLIBCXX_DEBUG
    __glibcxx_check_subscript(__n);
#endif
    return _M_instance[__n];
}

This means you can enable bounds checking for array the same way you do for vector and other stl debugging - by adding -D_GLIBCXX_DEBUG to your compile line. 这意味着您可以像对向量和其他stl调试一样启用对数组的边界检查 - 通过向编译行添加-D_GLIBCXX_DEBUG Eg: 例如:

g++ someAwesomeProgram.cpp -D_GLIBCXX_DEBUG

I just had a look at gcc trunk and apparently there is no reference to _GLIBCXX_DEBUG for array yet :(. http://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/include/std/array 我只是看看gcc的树干,显然没有提到但_GLIBCXX_DEBUG数组:(。 http://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/include/std/array

Hopefully it's not too far away. 希望它不会太远。 I imagine we will have safe iterators and all that for array in debug mode soon enough. 我想我们将有足够的安全迭代器以及调试模式中的所有数组。 In the meantime, this can be our little secret :-). 与此同时,这可能是我们的小秘密:-)。

template<class T, std::size_t N>
T const& at(std::array<T,N> const& arr, std::size_t pos){
#ifndef NDEBUG
  // debug versions, automatically range checked
  return arr.at(pos);
#else
  // release version, unchecked
  return arr[pos];
#endif
}    

template<class T, std::size_t N>
T& at(std::array<T,N>& arr, std::size_t pos){
  typedef std::array<T,N> const& const_array;
  // const_cast of the return is safe here because be pass a non-const array
  // const_cast for the argument is needed to avoid infinite recursion
  return const_cast<T&>(at(const_cast<const_array>(arr), pos));
}

Should do the job. 应该做的工作。 Just use at(arr, pos) consistently throughout the codebase. 只需at(arr, pos)整个代码库中使用at(arr, pos)

You can emulate the behaviour you desire: 您可以模仿您想要的行为:

#include <array>
#include <cassert>
#include <iostream>

#ifndef NDEBUG
template <typename T, std::size_t N>
struct my_array : std::array<T,N> {
 T& operator[](std::size_t n) {
   assert(n < N);
   return (*static_cast<std::array<T,N>*>(this))[n];
 }
 const T& operator[](std::size_t n) const {
   assert(n < N);
   return (*static_cast<const std::array<T,N>*>(this))[n];
 }
};
#else
// I would use Alias templates here, but isn't supported on my compiler yet!
template <typename T, std::size_t N>
struct my_array : std::array<T,N> {
};
#endif

It doesn't perfectly match std::array , but that could be fixed if it matters to you. 它与std::array不完全匹配,但如果对你很重要,可以修复它。 Then replace all reference to std::array with my_array and you'll get range checked operator[] for debug builds. 然后用my_array替换对std::array所有引用,你将获得调试版本的范围检查operator[]

(I'd have used template aliases to simplify the NDEBUG code, but I can't actually test that yet on my compiler) (我已经使用模板别名来简化NDEBUG代码,但我实际上无法在我的编译器上测试它)

It is not so much gcc as libstdc++ the Standard Library implementation that comes with gcc (you are free to use another implementation if you wish). libstdc++的是gcc附带的标准库实现(如果你愿意,可以自由使用另一个实现)。

libstdc++ has a preprocessor flag that can be used for debugging -D_GLIBCXX_DEBUG , however you should note that this debug mode changes the ABI of the types, and thus you need to link with libraries that have also been compiled with this debug mode enabled. libstdc++有一个预处理程序标志,可用于调试-D_GLIBCXX_DEBUG ,但是您应该注意,此调试模式会更改类型的ABI,因此您需要链接已启用此调试模式编译的库。 It can be painful. 这可能很痛苦。

libc++ is another implementation (nigh C++11 compliant) that is first aimed at Clang but should work on any compliant compiler. libc++是另一个实现(符合C ++ 11标准),它首先针对Clang,但应该适用于任何兼容的编译器。 It aims at maintaining ABI compatibility whether debugging is enabled or not. 它旨在维护ABI兼容性,无论是否启用调试。 It's not fully stable outside of OS X though (mostly because of locale) so might not be usable in your environment. 但它在OS X之外并不完全稳定(主要是因为语言环境),因此可能无法在您的环境中使用。

Note that both those libraries are Free Software, so if the check is not implemented, you can perfectly submit a patch. 请注意,这两个库都是自由软件,因此如果没有实现检查,您可以完美地提交补丁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM