This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Exceptions don't work correctly?


I got this when I was doing a simple test class for C++ (using egcs, as
gcc produced segfaulting code even more easily):

fishy:/home/raulir/C++> /usr/local/bin/g++ crash1.cc crash2.cc -o crash
fishy:/home/raulir/C++> ./crash
Segmentation fault
fishy:/home/raulir/C++>

I have included the source files, and it doesn't look like a problem in my
code:

(gdb) bt
#0  0x8054d08 in count_fdes (this_fde=0xca9)
#1  0x8054df8 in frame_init (ob=0x8061ba8)
#2  0x8054efb in find_fde (pc=0x804ada3)
#3  0x8055561 in __frame_state_for (pc_target=0x804ada3, state_in=0xbffff514)
#4  0x8054022 in next_stack_level (pc=0x804ada3, udata=0xbffff584,
    caller_udata=0xbffff514)
#5  0x8054149 in __throw ()
#6  0x804adb2 in MeasureTime::SetValue (this=0xbffff688, secs=0, usecs=-184012)
    at crash2.cc:72
#7  0x804b3d2 in Time::operator- (this=0xbffff6d0, right=@0xbffff6dc)
    at crash2.cc:138
#8  0x804a1a8 in main () at crash1.cc:17
#9  0x804a06b in ___crt_dummy__ ()

crash.hh:
--------------------------------------------------------------------------------

#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream.h>

class MeasureTime;
class TimeInterval;
class Time;

// Serves as base class for TimeInterval and Time.
// If an exception is thrown, the object is kept intact.

class MeasureTime
{
private:
  long _Secs,_Usecs;
protected:
  void FixUsecs(long *secs,long *usecs);
  friend ostream &operator<<(ostream &o,MeasureTime &t);
public:
  virtual long GetSecs(void) const { return _Secs; }
  virtual long GetUsecs(void) const { return _Usecs; }
  virtual void SetSecs(long secs);
  virtual void SetUsecs(long usecs);
  virtual void AddValue(long secs,long usecs);
  virtual const MeasureTime &operator-=(const MeasureTime &right);
  virtual const MeasureTime &operator+=(const MeasureTime &right);

  MeasureTime operator-(const MeasureTime &right);
  MeasureTime operator+(const MeasureTime &right);
  void SubValue(long secs,long usecs) { AddValue(-secs,-usecs); }
  void AddSecs(long secs) { AddValue(secs,0); }
  void SubSecs(long secs) { SubValue(secs,0); }
  void AddUsecs(long usecs) { AddValue(0,usecs); }
  void SubUsecs(long usecs) { SubValue(0,usecs); }
  void SetValue(long secs,long usecs);

  MeasureTime(void):_Secs(0),_Usecs(0) {}
  MeasureTime(long secs,long usecs):_Secs(secs),_Usecs(usecs) {}
  MeasureTime(const struct timeval &tv);
  virtual ~MeasureTime() {}
};

// Operates only on certain time intervals, does not know anything about
// current time or timezone. Time1-Time2 == TimeInterval

class TimeInterval:public MeasureTime
{
public:
  const TimeInterval &operator*=(long right);
  const TimeInterval &operator/=(long right);
  TimeInterval operator*(long right);
  TimeInterval operator/(long right);

  TimeInterval(long secs,long usecs):MeasureTime(secs,usecs) {}
  TimeInterval(struct timeval &val):MeasureTime(val) {}
  TimeInterval(void):MeasureTime() {}
  virtual ~TimeInterval() {}
};

// Operates on time, not time intervals, and handles timezones and such.
// :TODO: (currently doesn't support anything fancy like timezones)
//
// Time1-Time2 == TimeInterval == Time2-Time1

class Time:public MeasureTime
{
public:
  void SetCurTime(void);
  TimeInterval operator-(const Time &right);

  Time(void):MeasureTime() {}
  Time(struct timeval &tv):MeasureTime(tv) {}
  Time(long secs,long usecs):MeasureTime(secs,usecs) {}
  virtual ~Time() {}
};

--------------------------------------------------------------------------------
crash1.cc:

#include "crash.hh"

int main(int,char *[])
{
  Time old,cur;
  TimeInterval tv;
  
  try {
    old.SetCurTime();
    for(int i=0;i<1000000;i++);
    cur.SetCurTime();
  } catch(int a) {
    cout<<"Line "<<__LINE__<<": Catched exception "<<a<<'\n';
    return 1;
  }
  try {
    tv=cur-old;
  } catch(int a) {
    cout<<"Line "<<__LINE__<<": Catched exception "<<a<<'\n';
    return 1;
  }
  cout<<cur<<" : ";
  for(;;) cur-old;
  cout<<cur<<"\n";
  cout<<"1000000 loops took "<<tv<<'\n';
  return 0;
}

crash2.cc :

#include "crash.hh"

// Class MeasureTime

void MeasureTime::FixUsecs(long *secs,long *usecs)
{
  if(*usecs>-1000000&&*usecs<1000000) return;

  int i=(*usecs)/1000000;

  if(*usecs<0) {
    *secs-=i;
    *usecs+=1000000*i;
  }
  if(*usecs>1000000) {
    *secs+=i;
    *usecs-=1000000*i;
  }
}

const MeasureTime &MeasureTime::operator-=(const MeasureTime &right)
{
  long secs=_Secs-right._Secs,usecs=_Usecs-right._Usecs;

  FixUsecs(&secs,&usecs);
  if(secs<0||usecs<0) throw(1);
  _Secs=secs; _Usecs=usecs;
  return *this;
}

const MeasureTime &MeasureTime::operator+=(const MeasureTime &right)
{
  long secs=_Secs+right._Secs,usecs=_Usecs+right._Usecs;

  FixUsecs(&secs,&usecs);
  if(secs<0||usecs<0) throw(1);
  _Secs=secs; _Usecs=usecs;
  return *this;
}

MeasureTime MeasureTime::operator-(const MeasureTime &right)
{
  MeasureTime val=*this;

  val.operator-=(right);
  return val;
}

MeasureTime MeasureTime::operator+(const MeasureTime &right)
{
  MeasureTime val=*this;

  val.operator+=(right);
  return val;
}

void MeasureTime::SetSecs(long secs)
{
  if(secs<0) throw(1);
  _Secs=secs;
}

void MeasureTime::SetUsecs(long usecs)
{
  if(usecs<0) throw(1);
  _Usecs=usecs;
}

void MeasureTime::SetValue(long secs,long usecs)
{
  FixUsecs(&secs,&usecs);
  if(secs<0||usecs<0) throw(1);
  _Secs=secs; _Usecs=usecs;
}

void MeasureTime::AddValue(long secs,long usecs)
{
  secs+=_Secs; usecs+=_Usecs;
  if(secs<0||usecs<0) throw(1);
  _Secs=secs; _Usecs=usecs;
}

MeasureTime::MeasureTime(const struct timeval &val)
{
  SetSecs(val.tv_sec);
  SetUsecs(val.tv_usec);
}

// Class TimeInterval

const TimeInterval &TimeInterval::operator*=(long right)
{
  SetValue(GetSecs()*right,GetUsecs()*right);
  return *this;
}

TimeInterval TimeInterval::operator*(long right)
{
  TimeInterval val;

  val.SetValue(GetSecs()*right,GetUsecs()*right);
  return val;
}

TimeInterval TimeInterval::operator/(long right)
{
  TimeInterval val;

  val.SetValue(GetSecs()/right,GetUsecs()/right);
  return val;
}

const TimeInterval &TimeInterval::operator/=(long right)
{
  if(right<=0) throw(1);
  SetValue(GetSecs()*right,GetUsecs()*right);
  return *this;
}

// Class Time

void Time::SetCurTime(void)
{
  struct timeval tv;

  gettimeofday(&tv,NULL);
  SetValue(tv.tv_sec,tv.tv_usec);
}

TimeInterval Time::operator-(const Time &right)
{
  TimeInterval val;
  long secs,usecs;
  
  try {
    secs=right.GetSecs()-GetSecs();
    usecs=right.GetUsecs()-GetUsecs();
    val.SetValue(secs,usecs);
  } catch(int) {
    // The object hasn't changed and an exception was thrown, so we'll try
    // this..
    secs=GetSecs()-right.GetSecs();
    usecs=GetUsecs()-right.GetUsecs();
    val.SetValue(secs,usecs);
  }
  return val;
}

// Friend functions

ostream &operator<<(ostream &o,MeasureTime &t)
{
  return o<<t.GetSecs()<<" seconds, "<<t.GetUsecs()<< " microseconds";
}
--------------------------------------------------------------------------------

Yes I know they're long, but I tried to make them shorter and always the
bug disappeared :(

The correct behavior for this is an infinite loop, because I have
"for(;;) cur-old;" in the test code :)

If I concatenate crash1.cc and crash2.cc, the thing works. Urrgh.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]