GCC STL Bound Checking

GCC STL bound checking

You can activate runtime iterator and bounds checking by compiling with -D_GLIBCXX_DEBUG. Also note that random-access containers provide the always bounds-checking at()-operation in addition to operator [].

References:

GCC STL debug mode:
http://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode_using.html#debug_mode.using.mode

at() operation: std::vector::at(), std::deque::at() and std::array::at()

GCC STL bound checking

You can activate runtime iterator and bounds checking by compiling with -D_GLIBCXX_DEBUG. Also note that random-access containers provide the always bounds-checking at()-operation in addition to operator [].

References:

GCC STL debug mode:
http://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode_using.html#debug_mode.using.mode

at() operation: std::vector::at(), std::deque::at() and std::array::at()

Automatically check bounds in std::vector

To me, this utility template seems to be so straight-forward that I'd
expect it to exist

For gcc it does exist. gcc libstdc++ has a set of debug containers. For std::vector it has __gnu_debug::vector debug container. See documentation.

Bound checking of std::array in Debug version of GCC

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. Then replace all reference to std::array with my_array and you'll get range checked operator[] for debug builds.

(I'd have used template aliases to simplify the NDEBUG code, but I can't actually test that yet on my compiler)

Is it possible to enable array bounds checking in g++?

You can use a static analyser such as Cppcheck. When run on your above code:


$ cppcheck --enable=all test.cpp
Checking test.cpp...
[test.cpp:6]: (style) Variable 'arr' is not assigned a value
[test.cpp:8]: (error) Array 'arr[2]' index 4 out of bounds

You can integrate Cppcheck into your build procedure and consider your code built successfully only if Cppcheck passes.

How to make std::vector's operator[] compile doing bounds checking in DEBUG but not in RELEASE

Visual Studio 2005 and 2008 already do bounds-checking on operator[] by default, in both debug and release builds.

The macro to control this behavior is _SECURE_SCL. Set it to 0 to disable bounds-checking.

Their current plan in VS2010 is to disable bounds-checking by default in release builds, but keep it on in debug. (The macro is also getting renamed to _ITERATOR_DEBUG_LEVEL. I don't know if there's any formal documentation available on it yet, but it has been mentioned here and here)

C++: Vector bounds

The book is a bit vague. It's not as much a "runtime error" as it is undefined behaviour which manifests at runtime. This means that anything could happen. But the error is strictly with you, not with the program execution, and it is in fact impossible and non sensible to even talk about the execution of a program with undefined behaviour.

There is nothing in C++ that protects you against programming errors, quite unlike in Java.


As @sftrabbit says, std::vector has an alternative interface, .at(), which always gives a correct program (though it may throw exceptions), and consequently one which one can reason about.


Let me repeat the point with an example, because I believe this is an important fundamental aspect of C++. Suppose we're reading an integer from the user:

int read_int()
{
std::cout << "Please enter a number: ";
int n;
return (std::cin >> n) ? n : 18;
}

Now consider the following three programs:

The dangerous one: The correctness of this program depends on the user input! It is not necessarily incorrect, but it is unsafe (to the point where I would call it broken).

int main()
{
int n = read_int();
int k = read_int();
std::vector<int> v(n);
return v[k];
}

Unconditionally correct: No matter what the user enters, we know how this program behaves.

int main() try
{
int n = read_int();
int k = read_int();
std::vector<int> v(n);
return v.at(k);
}
catch (...)
{
return 0;
}

The sane one: The above version with .at() is awkward. Better to check and provide feedback. Because we perform dynamic checking, the unchecked vector access is actually guaranteed to be fine.

int main()
{
int n = read_int();

if (n <= 0) { std::cout << "Bad container size!\n"; return 0; }

int k = read_int();

if (k < 0 || k >= n) { std::cout << "Bad index!\n"; return 0; }

std::vector<int> v(n);
return v[k];
}

(We're ignoring the possibility that the vector construction might throw an exception of its own.)

The moral is that many operations in C++ are unsafe and only conditionally correct, but it is expected of the programmer that you make the necessary checks ahead of time. The language doesn't do it for you, and so you don't pay for it, but you have to remember to do it. The idea is that you need to handle the error conditions anyway, and so rather than enforcing an expensive, non-specific operation at the library or language level, the responsibility is left to the programmer, who is in a better position to integrate the checking into the code that needs to be written anyway.

If I wanted to be facetious, I would contrast this approach to Python, which allows you to write incredibly short and correct programs, without any user-written error handling at all. The flip side is that any attempt to use such a program that deviates only slightly from what the programmer intended leaves you with a non-specific, hard-to-read exception and stack trace and little guidance on what you should have done better. You're not forced to write any error handling, and often no error handling ends up being written. (I can't quite contrast C++ with Java, because while Java is generally safe, I have yet to see a short Java program.)</rantmode>



Related Topics



Leave a reply



Submit