Exception handling with STL Vectors

I have been facing problems with the programs crashing, due to accessing wrong index (out of range index).

Just now checked that vector::at is the best method to access the individual elements of a vector list. As it throws an 'out of range' exception.

Unfortunately, I have written all my programs until now using vector::operator[]. Cant see an error handling procedure for it. Is it possible that I can make it throw an exception, instead of getting the program crashed?
Last edited on
If you only want this to debug your program, you can try something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <vector>
using namespace std;

template <class T>
struct MyVector : public vector<T>
{
    T & operator[](unsigned i)
    {
        return vector<T>::at(i);
    }
};

#define vector MyVector

int main()
{
    vector<int> v;

    v.push_back(2);	

    cout << v[0] << endl;
    cout << v[1] << endl;

    return 0;
}

Last edited on
closed account (z05DSL3A)
I think that some compiler manufacturers put error handling on the vector::operator[] but it is not specified either way in the Standard. The best thing to do is check the index is in range yourself before using it.
Did u mean in the main(),

vector<int> v;

or

MyVector<int> v;

The first one. I assume that you don't want to change your existing code.

'vector' will be turned into 'MyVector' by the preprocessor. (#define vector MyVector )
Last edited on
I think that some compiler manufacturers put error handling on the vector::operator[] but it is not specified either way in the Standard. The best thing to do is check the index is in range yourself before using it.


I always have done like that.

My boss who is a Python programmer is using SWIG interface to invoke C++ functions from Python (as its faster). I do the coding in C++. In the beginning I was doing all the checks, but my boss asked me to remove all the checks to speed up further. And now after two years, he wants some kindof error handling and all the codes now need to be modified.
@m4ster r0shi

Oops, I overlooked the pre-processor line last time.

I was wondering if it wont replace the 'vector' in this block?

1
2
3
4
5
6
7
8
template <class T>
struct MyVector : public vector<T>
{
    T & operator[](unsigned i)
    {
        return vector<T>::at(i);
    }
};



Did it compile successfully?
luckycusp wrote:
I was wondering if it wont replace the 'vector' in this block?

It won't replace it, as the #define directive isn't met yet at that point.
It will only replace 'vector' occurrences after the #define directive.

luckycusp wrote:
Did it compile successfully?

Yes. See here -> http://codepad.org/lTXkoSwF
Last edited on
Wow, I learnt something new today! Thanks a lot.
Hello again,

I have a doubt with usage of 'at' function of vector in the case of multi-dimensional arrays. How do I use it?

1
2
3
4
5
vector< vector<int> > My2DVec(3,vector<int> (5)); /* A 3*5 2D Matrix */

cout<<My2DVec[2][3]; //Classic way using operator[]

cout<<(My2DVec.at(2)).at(3); //Using "at" operator.. does it work? Any other elegant way?? As I also got 3D vectors to deal with :( 
No, the chained calls to at() are the only way. Unfortunately the nesting of STL containers provides for some unwieldy syntax, an issue that many people agree exists with the STL. If you want to eliminate that, you'll need to write a facade that provides operator() as the element-access operator (because operator[] only accepts a single parameter).

1
2
3
4
struct ThreeDMatrix {
    // Lots of stuff
    int operator()( int x, int y, int z ) const;
};

Using a #define like that seems like a terrible idea. If you need to refactor the code then refactor the code correctly. Adding a #define like that is going to be a nightmare and it will create more problems then it will solve. If you use the .at() call then you need to add try..catch blocks to handle the exception. Or you can manually check the indices prior to accessing the operator[]. Even then you still might have to throw or return an error from a function somehow. If you are required to do the checks then it probably doesn't make much difference either way. I'm surprised that your boss told you to remove the checks due to performance constraints and now wants you to add it back. The original suggestion seemed rather silly. I don't see how verifying an array index is going to slow your program down considerably.
@Kempofighter

Ofcourse I did not use the #define method, as things could get really messy. I just manually changed the array access with .at() calls. Probably another 3-4 days work I guess! Got nothing else to do, so rather 'clean' it up.

My boss isnt a programmer, so he did not understand. I tried to explain but at that time he did not want it. Now he realises the mistake. We all learn from mistakes.

How about using some regex?


$ tail test.cc
    v1[0][1][2] = asdf;
    v2[asdf] = 1;
$ perl -pe 's/\[(.*?)\]/\.at\($1\)/g' test.cc > new.cc
$ tail new.cc
    v1.at(0).at(1).at(2) = asdf;
    v2.at(asdf) = 1;
$
moorecm

I like ur approach ;) But it will work only for 1D vectors.

2D Vector is accessed in this way
My2DVec[2][3] <==> (My2DVec.at(2)).at(3);

3D Vector
My3DVec[2][3][4] <==> ((My3DVec.at(2)).at(3)).at(4);
I'm working on it...so far I can only get the first ones resolved:


$ perl -pe 's/([_\w][_\w\d]*)\[(.*?)\]/\($1\.at\($2\)\)/g' test.cc
    (v1.at(0))[1][2] = asdf;
    (v2.at(asdf)) = 1;
$
Last edited on
Ok, I have one that works (in simple cases)...if you run it through a few times. I would watch out for the way it's looking for (-something-greedily-)[ for the 2+ runs. It's worth a quick shot, though.


$ tail test.cc
    v1[0][1][2] = asdf;
    v2[asdf] = 1;
$ perl -pe 'while( s/((?:[_\w][_\w\d]*)|\(.*\))\[(.*?)\]/\($1\.at\($2\)\)/g ) {}' test.cc
    (((v1.at(0)).at(1)).at(2)) = asdf;
    (v2.at(asdf)) = 1;
$


Hope this helps.
Last edited on
Topic archived. No new replies allowed.