1

Lots of times i've made small mistakes where indexes of beyond the bounds of an array or a memory allocation. Sometimes it may not cause a problem at all and go by unnoticed.

In C#, which I am used to, any attempt to go beyond the bounds of an array immediately triggers an exception and breaks at that point. But in C++ there may or may not be an exception, and the program might continue normally with an unlucky bug. I'm wondering if there's anything I can do to get the same behavior in C++. Thanks for your help.

  • 5
    One way to avoid this problem is to never use manual memory allocation. Instead use `std::vector` and index using at() – drescherjm Dec 10 '19 at 18:29
  • 3
    Use `std::array` for fixed-size arrays and, as above, take advantage of `at()` for bounds checking. – user4581301 Dec 10 '19 at 18:31
  • 1
    Visual studio also invokes a prompt box with the message "vector/array subscript out of range" when out of bounds indices are accessed, but only in versions after 2010 and in Debug mode. – Uninitialized Dec 10 '19 at 18:37
  • 2
    Perhaps what you want is a runtime memory-debugger tool? Wikipedia lists a number of them, most of which will help you detect out-of-range accesses: https://en.wikipedia.org/wiki/Memory_debugger – Jeremy Friesner Dec 10 '19 at 18:39
  • 2
    The reasoning for this: C++ follows an ideology of making a program only pay for what the program needs. The result of this ideology is faster programs as there is no extra "Just in case" work performed. You want the check, you explicitly ask for the check. Bounds checks have a cost, and a program that's written correctly does not need mandatory bounds checks at each access. This check, if necessary, has already been performed. – user4581301 Dec 10 '19 at 18:39
  • Possible duplicate of https://stackoverflow.com/questions/5594686/gcc-stl-bound-checking – Galik Dec 10 '19 at 18:45
  • 1
    Also use [assert](https://en.cppreference.com/w/cpp/error/assert) liberally to check function pre-conditions, bounds etc. – Galik Dec 10 '19 at 18:48
  • GCC debug library https://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode_using.html#debug_mode.using.mode – Galik Dec 10 '19 at 18:54

2 Answers2

4

Depending on what you use, there's a few possibilities. Obviously, the answer is: Don't go out of bounds. But how? Well you can always check the length before doing access, to be sure your index is inside the boundaries of the array.

As for memory allocation, well you should use std::vector for a dynamic array, or std::array for a fixed-size array.

With both of those containers, you can use the member function at which will throw an std::out_of_range exception if you go out of bounds. If you use the operator[], you will not have that check.

You have std::vector::size() and std::array:size() to give you the size (e.g. useful for a for loop where you specify the index) and you can always use a for-range loop to be sure to stay inside the bounds (as long as you don't modify the vector in the loop).

Rosme
  • 1,049
  • 9
  • 23
  • 2
    Note that you can modify the vector in the loop, as long as you don't do anything that invalidates iterators. In other words you can't add or remove elements but you can modify the elements it already contains. – François Andrieux Dec 10 '19 at 18:36
2

Visual Studio offers the /RTC (run-time error checks) option. However there is this caveat.

Run-time error checks are a way for you to find problems in your running code; for more information, see How to: Use Native Run-Time Checks.

If you compile your program at the command line using any of the /RTC compiler options, any pragma optimize instructions in your code will silently fail. This is because run-time error checks are not valid in a release (optimized) build.

You should use /RTC for development builds; /RTC should not be used for a retail build. /RTC cannot be used with compiler optimizations (/O Options (Optimize Code)). A program image built with /RTC will be slightly larger and slightly slower than an image built with /Od (up to 5 percent slower than an /Od build).

Then there is the /GS (Buffer Security Check) option. However again there is a caution.

The /GS compiler option does not protect against all buffer overrun security attacks. For example, if you have a buffer and a vtable in an object, a buffer overrun could corrupt the vtable.

Even if you use /GS, always try to write secure code that has no buffer overruns.

Then there is BoundsChecker.

You may also find the Checked C project from Microsoft of interest as well. See this article https://www.infoq.com/news/2016/06/checked-c/

Checked C is open sourced on GitHub, including the specification, a clang implementation and a LLVM implementation. Developers interested in this project are invited to contribute, either to improve the specification, proposing new functionality such as type casting or memory management, adding tests, or extending other compilers to support Checked C.

Richard Chambers
  • 16,643
  • 4
  • 81
  • 106