-1

So I have this simple class, that throw an array, so the main can catch it and interpret it

#include "r0t0r.h"

using namespace std;


rotor::r0t0r(){
    int a[2]={5,6};
    throw a;
}

In my main, I try to catch this array:

int main(int argc, char **argv){

    try{
        r0t0r a;
        std::cout << "123" << std::endl;
    }
    catch(int e[2]){
        std::cout << e[0] << std::endl;
    }
}

but my output is some gibberrish.

Help?

Edit:

I just tried the below, it is due the empty constructor.

class rotor{
    public:
  rotor();
    rotor(int a[2]);
};

rotor::rotor(){
  int b[2]={12,2};
  throw b;
}

rotor::rotor(int a[2]){

    throw a;
}

using namespace std;

int main(int argc, char **argv){
    try{
      //int b[2]={12,2};
      //rotor a(b); 
//this output perfect with a contructor with argument


      rotor a;
//this output gibberish


    }
    catch(int e[2]){
        std::cout << e[0] << std::endl;


    }

}
Tom chan
  • 365
  • 3
  • 18

2 Answers2

2

Consider this:

#include <iostream>
#include <typeinfo>

int main(int argc, char **argv)
{
    try
    {
        int a[2]={5,6};
        std::cout << "Address of A " << a << std::endl;
        throw a;
    }
    catch(int e[2])
    {
        std::cout << "Type of E " << typeid(e).name() << std::endl;
        std::cout << "Address of E " << e << std::endl;
        std::cout << e[0] << std::endl;
    }
}

This now outputs the type of the caught object:

 $ ./a.out 
 Address of A 0x7fff55986a40
 Type of E Pi
 Address of E 0x7fff55986a40
 5

Pi being a pointer to int:

$ c++filt Pi
int*

What is going on here is the decay of the array a[2] to a pointer - int *. Read more about array to pointer decay here.

What appears to be throw and catch of the contents of the array by value is in fact a throw and catch of its pointer by value instead.

You are throwing the address of a stack variable, and then attempting to access it beyond its lifetime. This is undefined behaviour.

This will appear to work in trivial cases such as mine as nothing has yet overwritten the stack, but will then fail as the program gains complexity.

To get the behaviour you expect, consider using std::array<int>

#include <iostream>
#include <typeinfo>
#include <array>

int main(int argc, char **argv)
{
    try
    {
        std::array<int, 2> a={{5,6}};
        throw a;
    }
    catch(std::array<int, 2> e)
    {
        std::cout << e[0] << std::endl;
    }
}
Community
  • 1
  • 1
marko
  • 9,029
  • 4
  • 30
  • 46
  • This definitely make sense, but can you explain this only apply to the empty constructor?? – Tom chan Nov 14 '15 at 10:12
  • Both constructors look equally suspect, and both suffer from undefined behaviour. However, the constructor taking a array argument receives a decayed pointer-to-an-array which is already on the stack when it's called and is probably still there when the exception is caught, so the problem is not apparent. – marko Nov 14 '15 at 10:17
  • ya, i just try it out now with a constructor with a bit more code in it and it s not working again – Tom chan Nov 14 '15 at 10:23
  • Just updated the question. My solution requires C++11 – marko Nov 14 '15 at 10:29
  • No. the TL;DR answer is that `std::array` is a class which enforces copy-by-value semantics and to which array-to-pointer decay does not apply. This means that a copy is made when the object is thrown and caught. – marko Nov 14 '15 at 10:33
  • Yes. Or `std::vector`. – marko Nov 14 '15 at 10:40
1

You are throwing an array address and catch it with an int, Throwing an int value will resolve your problem.