# stl::vector, .at(), operator[ ]

This topic is 4864 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi everyone, I was wondering if there was an (easy) way to do this: using stl::vector's for my array stuff, currently I am using myVector to get the i'th element of a vector.. now the operator[] does NOT do bounds checking, where as myVeector.at(i) does do bounds checking... is there an easy way via a compiler option (using g++) so that I can force a bounds check on [], rather that change all my [] calls it .at() calls, debug my code and then change back to using []? Best Regards

##### Share on other sites
There's a couple of ways you could hack around it but stop a moment and think about the reason for doing so if you decide to do so. If you go trample outside your array bounds when in debug mode how can you be so sure that under certain circumstances you won't be doing it when you go into release mode?

If you can't be 100% sure that you're not going to go out of bounds (like using i != v.size() for loop termination etc) then it's probably, in the long run, a lot safer to just stick with the at calls instead.

Anyhow, if you still want to skip the saftey-belt when going release simple condiditional compilation and a typedef should solve it easily, implementation left as an exercise to the reader but should take ~3minutes.

##### Share on other sites
Don't know about gcc + libstdc++, but the Dinkumware STL used by Microsoft's Visual Studio actually does bounds checking in operator [] (via an assertion; that's legal, it just mustn't throw an exception like at() is guaranteed to do, regardless of debug or release mode). Maybe that's sufficient for you.

Otherwise, well, I think you would be better off by replacing any [] with .at() instead of hacking something together (like a wrapper which calls .at() in operator[] :))

-Markus-

##### Share on other sites
truth is that all I want is an assert() so that I can debug easily... I guess I will just make my hack real quick.... as for my motivation: I just want to _CHECK_ that I do not go outside my array bounds in an automated way... as of right now my code crashes occasionally, and has occasional odd behavious... thus I am convinced that it is a bad memory writing (before I was using raw pointers, and took the day to move it to stl::vector) but still have wierd seg faults which suggest going out of bounds on my arrays.... I stay away from exception handling like the plague.... some love it, but I am not so crazy about typing "catch" everytime I do an array access... I jsut want to know where (and if) I go out of my array bounds...

Best Regards

##### Share on other sites
maybe do

template<typename T>class TestVector : std::vector<T> {public:    //constructors etc.    //...    reference operator[](size_type index) {        return at(index);    }};

or something.

##### Share on other sites
Not sure whether STLport would do this for you in debug mode. Worth a look anyway.

##### Share on other sites
I did almost the exact samething as posed by petewood for the hack to force vector bounds checking, though I was a bit more paranoid:

template<class T> class kector:public vector<T>{public:  kector(int sz):vector<T>(sz) {}  kector(void):vector<T>() {}  kector(const kector &obj):vector<T>(obj) {}  reference  operator[](size_t __n)   {     ASSERT(0<=__n && __n<size());    return *(begin() + __n);   }       const_reference  operator[](size_t __n) const   {    ASSERT(0<=__n && __n<size());    return *(begin() + __n);   }  };

though, after I changed by vectors to kectors, I never got an out of bounds error, ever.... just to check that it was actually checking the bounds I went ahead and tested it and deliberatly did an array acces out of bounds, and the ASSERT, well asserted.... so now I know that my array writing is within bounds always.... damn... maybe I ahve a wild poiner somewhere... but I ahve been writing my stuff uber-paranoid like though.....

one thing that bothered me was the the compiler (g++) gave a warning when I used the return types const_reference and reference for the operator calls.. a quick look into the file of the #include <vector> and within it, to something like "bits/stl_vector" came to the lines within the declaration of the vector template:

typedef _Tp 						value_type;typedef value_type& 					reference;typedef const value_type& 				const_reference;

but when I made my operators return types "const T&" and "T&" the compiling failed when it came up to a vector<bool>.. any thoughs?

##### Share on other sites
Use 'typedef std::vector<T>::whatever whatever;'.

Speaking of code to help find bugs, here's something I wrote once:

#ifndef DETECTOR_HPP#define DETECTOR_HPP/** \file detector.hpp    \brief The declaration of the DamageDetector class. */#include "assert.hpp"/** \brief A DamageDetector object is used for detecting damaged objects.        If it somehow gets overwritten, then copying, destroying, assigning,    and invoking check will (or at least probably; there's a small chance    it might get over written to look like it's in a valid state) result in    an assertion failure.        Destroying an object will put a DamageDetector object into an invalid state,    so attempting to use a destroyed object (i.e., with a stale reference, or a    dangling pointer) will also cause an assertion failure.        Can also help find buffer overflows and fence post errors, as such an object    will not have been constructed, and will generate an error if you try to    use them.        If debugging is disabled, DamageDetector does nothing.        So, add a public DamageDetector in your classes and remember to check it at    the start of your functions to help ensure you're using a real object, and    not just garbage floating around somewhere. */class DamageDetector {  #ifndef NDEBUG // Debug version:  protected:   DamageDetector *self;    public:      /** \brief DamageDetector default constructor.    */   DamageDetector(): self(this)    {}      /** \brief DamageDetector copy constructor.       \param ref The DamageDetector being copied.              Checks the object it's being copied from for damage, other than       that it's identical to default constructor.    */   DamageDetector(const DamageDetector &ref): self(this)    {     ref.check();    }      /** \brief DamageDetector destructor.              Checks itself for damage and then puts itself into an invalid state       so that it will notice if you try to use it after it's been destroyed.    */   ~DamageDetector()    {     check(); // This can throw an exception, and exceptions shouldn't be thrown from destructors. This should be interesting.     self = 0;    }      /** \brief DamageDetector copy constructor.       \param ref The DamageDetector being assigned from.       \return A reference to itself.              Checks itself and the reference for damage, then returns a reference to itself.    */   DamageDetector & operator = (const DamageDetector &ref)    {     check();     ref.check();     return *this;    }      /** \brief Equality operator       \param ref The DamageDetector being compared.       \return true.              Checks itself and the reference for damage, then returns true.    */   bool operator == (const DamageDetector &ref) const    {     check();     ref.check();     return true;    }         /** \brief Inequality operator       \param ref The DamageDetector being compared.       \return false.              Checks itself and the reference for damage, then returns false.    */   bool operator != (const DamageDetector &ref) const    {     check();     ref.check();     return true;    }      /** \brief Checks for damage.              If there is a problem, an assertion failure happens. You should try to call this at the start of all your functions.              \see assert setAssertAction    */   void check(void) const    {     assert(this && this == self);     self = this; // If this did screw up, reset it to a proper value so this doesn't continually show up.    }    #else // Release version; does nothing.  public:   void check(void) const    {}  #endif };#endif

Stick one of this in your classes and call check() on it at the start of all your functions.

Helps catch buffer overruns, data corruption, dangling pointers and references, using uninitialized memory, bad pointers, etc.

##### Share on other sites
You could allways open up your headers and throw an assert() in there yourself... not really recommended from a system's administration POV... but if you're lazy like me, it's the easiest way :P.

e.g. for vector<> on my debian box I'd go into:

/usr/include/c++/3.3/bits/stl_vector.h (not .hh or .hpp like it should be :-()

And add #include <cassert> with the rest of the headers in the include guard... and change:

reference
operator[](size_type __n) { return *(begin() + __n); }

and:

const_reference
operator[](size_type __n) const { return *(begin() + __n); }

to:

reference
operator[](size_type __n) { assert( __n < this->size() ); return *(begin() + __n); }

and:

const_reference
operator[](size_type __n) const { assert( __n < this->size() ); return *(begin() + __n); }

Patches should be able to work even :).

1. 1
2. 2
JoeJ
16
3. 3
4. 4
5. 5
frob
11

• 13
• 16
• 13
• 20
• 12
• ### Forum Statistics

• Total Topics
632178
• Total Posts
3004607

×