2

Consider this code

#include <vector>
#include <iostream>
main()
{
    std::vector <int> x(1);
    for(int q=0;; q++)
    {
        int y = x[q];
        std::cout << q << " ";
    }
}

On my system with g++, this prints up to 32570 before crashing with Segmentation fault (core dumped). Presumably, It takes that long because ~32570 is the size of the smallest chunk of memory that the OS and/or allocator will allocate to the vector. But of course, any time we do an operation like this past the end of the array is normally a bug. So it would be nice if I could have the program exit with a helpful error message whenever this occurs.

A few years ago with Xcode I recall that behavior occurring where it would exit with the type (and name?) of the std::vector. Currently I'm on Linux with g++. Is there any solution along these lines (or something else)?

Matt Munson
  • 2,903
  • 5
  • 33
  • 52
  • 2
    Related: [How to make std::vector's operator compile doing bounds checking in DEBUG but not in RELEASE](http://stackoverflow.com/q/1290396/96780) – Daniel Daranas Mar 23 '16 at 08:12
  • 1
    I know this still requires changes in code, but iterating over containers and certainly the range-based-for eliminate most of these issues without having to investigate why the program stopped. I admit the exiting with a message is better than undefined behavior like overwriting memory. – stefaanv Mar 23 '16 at 08:12
  • 2
    Related: [No compilation error or run time error when index out of range of vector class?](http://stackoverflow.com/q/27754726/96780). – Daniel Daranas Mar 23 '16 at 08:13

2 Answers2

2

You can use the std::vector::at member function which throws an out_of_range exception if your index violates the vector's range.

#include <vector>
#include <iostream>

int main() {
  std::vector <int> x(1);
  for(int q=0;; ++q) {
    int y = x.at(q);
    std::cout << q << " ";
  }
}
101010
  • 41,839
  • 11
  • 94
  • 168
  • Good to know. Although this would require me to replace all the element access calls in my program. I would still like to have a compiler option if possible. – Matt Munson Mar 23 '16 at 08:07
2

Compile with -D_GLIBCXX_DEBUG to enable debug mode in STL containers.

Alternatively you can also use specific debug containers which live in the __gnu_debug namespace, e.g. __gnu_debug::vector:

#include <iostream>
#include <debug/vector>

int main()
{
    __gnu_debug::vector <int> x(1);
    for(int q = 0; ; q++)
    {
        int y = x[q];
        std::cout << q << " ";
    }
}
Paul R
  • 208,748
  • 37
  • 389
  • 560
  • 1
    I guess the advantage of debug containers is you can isolate specific containers and then easily switch them over std:: containers later on? Is there anyway I can change this output or interpret it somehow? `Objects involved in the operation: sequence "this" @ 0x0x7ffc2b96e950 {type = NSt7__debug6vectorIiSaIiEEE;}` – Matt Munson Mar 23 '16 at 09:01
  • Unfortunately I think you're stuck with the standard debug error messages, unless you want to start hacking the libstdc++ source arouund. Having said that though, see [_GLIBCXX_DEBUG_VERIFY](https://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode_design.html). – Paul R Mar 23 '16 at 09:11
  • do you know if -D_GLIBCXX_DEBUG is generally compatible with boost? – Matt Munson Mar 23 '16 at 11:30
  • boost references `_GLIBCXX_DEBUG` in a couple of headers (`asio/buffer.hpp` and `detail/container_fwd.hpp`), but I think it uses its own debug mechanism internally. – Paul R Mar 23 '16 at 12:55
  • I couldn't get -D_GLIBCXX_DEBUG to work with my project. I think it was conflicting with boost or cpp-netlib. Replacing most of my std::vector with __gnu_debug::vector did the trick though, and wasn't too difficult. – Matt Munson Mar 23 '16 at 13:07
  • For future reference you could perhaps `#define _GLIBCXX_DEBUG` locally inside your source files, after any boost includes but before any STL includes. Alternatively just use `using __gnu_debug::vector;`, which I guess is what you did. – Paul R Mar 23 '16 at 13:11