Exceptions don't work correctly?
Rauli Ruohonen
raulir@fishy.pp.sci.fi
Mon Oct 6 14:29:00 GMT 1997
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.
More information about the Gcc-bugs
mailing list