Topic: Exception handling question


Author: Johann Klugsberger <klugsber@austria.ds.philips.com>
Date: 1998/06/09
Raw View
You shure are catching CException references, arent you? It should work this way

try
{
}
catch (CException& ex)
{
}

Hans

Albrecht Reimann wrote:

> In order to decouple exception handling, exception description, and
> exception reporting, I use a three-fold exception object structure:
> 1. CException is a basic exception class, which holds a pointer to a
> 2. CReport, which contains an situation-dependent error description, and a
>     virtual reporting method, which is used by a
> 3. CReportSink object to pass this description ahead to the appropriate
> reporting
>     channel (e.g. OLE IErrorInfo, Win/NT event log, message box, etc.).
>
> This way, I can still select the appropriate exception handling using
> specialized
> CException classes and corresponding catch()es, I can pass specialized
> descriptions
> for my exceptions, and I can pass these descriptions to specialized
> reporting channels.
>
> My problem is: I throw a simple exception with a specialized CMyReport.
> Then I catch a reference to this exception, but when I extract the
> report pointer, it turned to be a simple CReport object. My compiler (VC++5)
> simply replaces
> the __vfptr of CMyReport with a one for CReport, just before entering the
> catch() block.
> Do I do something wrong, is this a compiler bug, or is it a special
> Microsoft  feature ?
>
> Best regards
> Albrecht

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Albrecht Reimann" <NOSPAMare@basilproducts.dk>
Date: 1998/06/09
Raw View
>
>  Since you do not include any code, it is impossible to say if it is
>someting wrong with it.
>
As you ask for code,...


// The report sink just outputs exception descriptions ...
class CReportSink {
public:
    virtual unsigned doReport (char * text) {
        // pass text to the appropriate destination
    }
};


// The base report contains a description text for the exception..
class CReport {
public:
    CReport (char * aDescription) {
        theDescription = strdup(aDescription);
    };
    CReport (const CReport & org) {
        theDescription = strdup(org.theDescription);
    };
    virtual ~CReport (void) {
        if (theDescription)
            delete theDescription;
    };

    virtual unsigned doReport (CReportSink & aSink) {
        aSink.doReport (theDescription);
    };

protected:
    char * theDescription
};


// The exception holds a report with a description of the exception
class CException {
public:
    CException (CReport * aReport) {
        info = aReport;
    };
    CException (const CException & org) {
        assert (false);    // I don't want to provide a copy constructor,
... (I never reach here)
    };
    virtual ~CException (void) {
        if (info)
            delete info;
    };

    CReport * getInfo (void) {
        return info;
    };
    unsigned Report (CReportSink & aSink) {
        info->doReport (aSink);
    };

private:
    CReport * info;
};


// And an example of a specialized report class
class CMyReport : public CReport {
    CMyReport (char * aText,int aNum) : CReport (aText) {
        theNum = aNum;
    };
    CMyReport (const CMyReport & org) : CReport (org) {
        theNum = org.aNum;
    };

    // ...

    virtual unsigned doReport (CReportSink & aSink) {
        char buf [500];
        sprintf (buf,AFORMATSTRING,theDescription,theNum);
        aSink.doReport (buf);
    };
};

The try/catch:

try {
    if (1)                // check for "exception" condition
        throw CException(new CMyReport ("hello catch",13));
}
catch (CException & e) {
    CReportSink s;
    e.Report (s);
}

In my program, I would get a report "hello catch", ie. the catch would
execute CReport::doReport(), not CMyReport::doReport().


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/06/09
Raw View
Albrecht Reimann wrote:
>
> In order to decouple exception handling, exception description, and
> exception reporting, I use a three-fold exception object structure:
> 1. CException is a basic exception class, which holds a pointer to a
> 2. CReport, which contains an situation-dependent error description, and a
>     virtual reporting method, which is used by a
> 3. CReportSink object to pass this description ahead to the appropriate
> reporting
>     channel (e.g. OLE IErrorInfo, Win/NT event log, message box, etc.).
>
> This way, I can still select the appropriate exception handling using
> specialized
> CException classes and corresponding catch()es, I can pass specialized
> descriptions
> for my exceptions, and I can pass these descriptions to specialized
> reporting channels.
>
> My problem is: I throw a simple exception with a specialized CMyReport.
> Then I catch a reference to this exception, but when I extract the
> report pointer, it turned to be a simple CReport object. My compiler (VC++5)
> simply replaces
> the __vfptr of CMyReport with a one for CReport, just before entering the
> catch() block.
> Do I do something wrong, is this a compiler bug, or is it a special
> Microsoft  feature ?

I guess you did something like this:

class CException
{
  CReport* report;
public:
  CException(CReport* Report): report(Report) {}
  ~CException() { delete report; }
  // no copy constructor
// ...
};

If this is the case, you probably get the following scenario:

You do throw CException(someReport). This creates a temporary
CException, copies it and destroys it. On destruction, your
destructor does delete report, which destructs the report and
frees the memory. During the destruction of the report, it
is "Downcycled" into a CReport (since the last destructor called
is CReport::~CReport(), and in that it's dynamic type is CReport).
The deleting obviously leaves the memory of the vptr unchanged.
The Copy of the CException gets caught, and you dereference
report, which points to the deleted (former) object. Since this
was left with a CReport vtbl and was not yet overwritten,
it *looks* like a CReport object to the program. However, it's
really dead memory.

The solution is to handle copying properly. A possible solution
would be to add a reference count to CReport and delete only
if this reference count is zero:

class CException
{
  CReport* report;
public:
  CException(CReport* Report):
    report(Report)
  {
    ++(report->ref_count);
            // assumes CReport constructor sets ref_count to 0
  }
  CException(CException const& other):
    report(other.report)
  {
    ++(report->ref_count);
  }
  ~CException()
  {
    if (--(report->refcount))
      delete report;
  }
// ...
};


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: haberg@xxx.matematik.su.se (Hans Aberg)
Date: 1998/06/09
Raw View
In article <357d0c28.0@news.businessnet.dk>, "Albrecht Reimann"
<NOSPAMare@basilproducts.dk> wrote:

  You will have to do your debugging yourself -- I can only come up with a
suggestion what to search for:

>The try/catch:
>
>try {
>    if (1)                // check for "exception" condition
>        throw CException(new CMyReport ("hello catch",13));
>}
>catch (CException & e) {
>    CReportSink s;
>    e.Report (s);
>}

  But possibly you should have:

catch (CException & e) {
    CReportSink* s;
    e.Report (*s);
}

  Because otherwise you call "s" as automatic variable, and the virtual
information is lost.

  Anyway, things like that I think you should look for.

  Hans Aberg   * Anti-spam: Remove "xxx." from email address.
               * Email: Hans Aberg <mailto:haberg@xxx.member.ams.org>
               * Home Page: <http://www.matematik.su.se/~haberg/>
               * AMS member listing: <http://www.ams.org/cml/>


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/06/10
Raw View
Albrecht Reimann wrote:
>
> >
> >  Since you do not include any code, it is impossible to say if it is
> >someting wrong with it.
> >
> As you ask for code,...
>
> // The report sink just outputs exception descriptions ...
> class CReportSink {
> public:
>     virtual unsigned doReport (char * text) {
>         // pass text to the appropriate destination
>     }
> };
>
> // The base report contains a description text for the exception..
> class CReport {
> public:
>     CReport (char * aDescription) {
>         theDescription = strdup(aDescription);
>     };
>     CReport (const CReport & org) {
>         theDescription = strdup(org.theDescription);
>     };
>     virtual ~CReport (void) {
>         if (theDescription)
>             delete theDescription;
>     };
>
>     virtual unsigned doReport (CReportSink & aSink) {
>         aSink.doReport (theDescription);
>     };
>
> protected:
>     char * theDescription
> };
>
> // The exception holds a report with a description of the exception
> class CException {
> public:
>     CException (CReport * aReport) {
>         info = aReport;
>     };
>     CException (const CException & org) {
>         assert (false);    // I don't want to provide a copy constructor,
> ... (I never reach here)
>     };
>     virtual ~CException (void) {
>         if (info)
>             delete info;
>     };
>
>     CReport * getInfo (void) {
>         return info;
>     };
>     unsigned Report (CReportSink & aSink) {
>         info->doReport (aSink);
>     };
>
> private:
>     CReport * info;
> };
>
> // And an example of a specialized report class
> class CMyReport : public CReport {
>     CMyReport (char * aText,int aNum) : CReport (aText) {
>         theNum = aNum;
>     };
>     CMyReport (const CMyReport & org) : CReport (org) {
>         theNum = org.aNum;
>     };
>
>     // ...
>
>     virtual unsigned doReport (CReportSink & aSink) {
>         char buf [500];
>         sprintf (buf,AFORMATSTRING,theDescription,theNum);
>         aSink.doReport (buf);
>     };
> };
>
> The try/catch:
>
> try {
>     if (1)                // check for "exception" condition
>         throw CException(new CMyReport ("hello catch",13));
> }
> catch (CException & e) {
>     CReportSink s;
>     e.Report (s);
> }
>
> In my program, I would get a report "hello catch", ie. the catch would
> execute CReport::doReport(), not CMyReport::doReport().

I just compiled your posted code (after some obvious corrections
which cannot be the source of your problem) on g++ 2.8.1, and it
does exactly what you want it to do. Either this is not equivalent
to your real code (did you really cut&paste it?), or you've
encountered a compiler bug.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: jkanze@otelo.ibmmail.com
Date: 1998/06/10
Raw View
In article <357d0c28.0@news.businessnet.dk>,
  "Albrecht Reimann" <NOSPAMare@basilproducts.dk> wrote:
>
> >
> >  Since you do not include any code, it is impossible to say if it is
> >someting wrong with it.
> >
> As you ask for code,...

Which contains at least two errors.

> // The report sink just outputs exception descriptions ...
> class CReportSink {
> public:
>     virtual unsigned doReport (char * text) {
>         // pass text to the appropriate destination
>     }
> };
>
> // The base report contains a description text for the exception..
> class CReport {
> public:
>     CReport (char * aDescription) {
>         theDescription = strdup(aDescription);
>     };
>     CReport (const CReport & org) {
>         theDescription = strdup(org.theDescription);
>     };
>     virtual ~CReport (void) {
>         if (theDescription)
>             delete theDescription;

First case of (probable) undefined behavior: you don't show the
implementation of strdup.  It is NOT a standard function, but a frequent
extension, and in every case I am aware of, it is an extension to C,
and allocates using malloc.  Allocating with malloc and freeing with
delete is undefined behavior (as is using delete instead of delete[]
on an array).  Do not forget that one possible symptom of undefined
behavior is that the program will appear to work.

Anyway, I don't think that this is what is causing your symptoms.

>     };
>
>     virtual unsigned doReport (CReportSink & aSink) {
>         aSink.doReport (theDescription);
>     };
>
> protected:
>     char * theDescription
> };
>
> // The exception holds a report with a description of the exception
> class CException {
> public:
>     CException (CReport * aReport) {
>         info = aReport;
>     };
>     CException (const CException & org) {
>         assert (false);    // I don't want to provide a copy constructor,
> ... (I never reach here)

This one surprises me: you should get here.  Could it be that you have
assertions turned off.  Or that your compiler is optimizing away one
of the copies.  (The usual way of banning copy is by declaring a private
copy constructor, and not providing any implementation.)

Your symptoms could be easily explained by the compiler using the
memberwise default copy.  The CMyReport object has been deleted; the
destructor set the vptr for the CReport base class (which is destructed
after the CMyReport), but otherwise, the actual memory contents have
not been modified, even though the memory has been deallocated.  If
so, your actual virtual function call is on a deleted object: undefined
behavior that just happens to look like a call to the base class function.

>     };
>     virtual ~CException (void) {
>         if (info)
>             delete info;
>     };
>
>     CReport * getInfo (void) {
>         return info;
>     };
>     unsigned Report (CReportSink & aSink) {
>         info->doReport (aSink);
>     };
>
> private:
>     CReport * info;
> };
>
> // And an example of a specialized report class
> class CMyReport : public CReport {
>     CMyReport (char * aText,int aNum) : CReport (aText) {
>         theNum = aNum;
>     };
>     CMyReport (const CMyReport & org) : CReport (org) {
>         theNum = org.aNum;
>     };
>
>     // ...
>
>     virtual unsigned doReport (CReportSink & aSink) {
>         char buf [500];
>         sprintf (buf,AFORMATSTRING,theDescription,theNum);
>         aSink.doReport (buf);
>     };
> };
>
> The try/catch:
>
> try {
>     if (1)                // check for "exception" condition
>         throw CException(new CMyReport ("hello catch",13));
> }
> catch (CException & e) {
>     CReportSink s;
>     e.Report (s);
> }
>
> In my program, I would get a report "hello catch", ie. the catch would
> execute CReport::doReport(), not CMyReport::doReport().

--
James Kanze    +33 (0)1 39 23 84 71    mailto: kanze@gabi-soft.fr
        +49 (0)69 66 45 33 10    mailto: jkanze@otelo.ibmmail.com
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient   e objet --
              -- Beratung in objektorientierter Datenverarbeitung

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/   Now offering spam-free web-based newsreading


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: AllanW@my-dejanews.com
Date: 1998/06/10
Raw View
In article <357d0c28.0@news.businessnet.dk>,
  "Albrecht Reimann" <NOSPAMare@basilproducts.dk> wrote:
>
> // The exception holds a report with a description of the exception
> class CException {
> public:
>     CException (CReport * aReport) {
>         info = aReport;
>     };
>     CException (const CException & org) {
>         assert (false);    // I don't want to provide a copy constructor,
*** Why not?

> ... (I never reach here)
*** Beg to differ.

>     };
>     virtual ~CException (void) {
>         if (info)
>             delete info;
>     };
>
>     CReport * getInfo (void) {
>         return info;
>     };
>     unsigned Report (CReportSink & aSink) {
>         info->doReport (aSink);
>     };

You must have inserted the assert() for illustrative purposes only.  If you
had left it in and enabled asserts, you would see that it was being hit!

>         throw CException(new CMyReport ("hello catch",13));
This constructs a CMyReport on the free store, and passes it's address to the
constructor for a temporary CException.  Once the temporary is built, it is
COPIED somewhere so that it can be caught.

> catch (CException & e) {
This is a reference to that copy.

Why does throw use the copy constructor, instead of just throwing a reference
to the data you're throwing?  Consider:
    int CalcBonus(double amt,int num1, int num2, int num3) {
        PersistantStore Emps("Employee.Dat");
        try {
            // Look up the three employees
            Employee e1, e2, e3;
            Emps.Read(num1, e1);
            Emps.Read(num2, e2);
            Emps.Read(num3, e3);

            // Make sure they're all salaried
            if (e1.basis==Employee::HOURLY) throw e1;
            if (e2.basis==Employee::HOURLY) throw e2;
            if (e3.basis==Employee::HOURLY) throw e3;

            // Find the total number of cookie points
            int cookies = e1.cookies + e2.cookies + e3.cookies;
            if (cookies < 1) throw cookies;

            // Divide the bonus fairly
            float per_cookie = amt / float(cookies);
            e1.bonus = e1.cookies * per_cookie;
            e2.bonus = e2.cookies * per_cookie;
            e3.bonus = e3.cookies * per_cookie;

            // Save to persistant storage
            Emps.Write(num1, e1);
            Emps.Write(num2, e2);
            Emps.Write(num3, e3);
        }
        catch (Employee e) {
            // ... Report error including employee name
            return 1; // Invalid employee for this function
        }
        catch (int cookies) {
            // ... Report that no cookie points equals no bonus
            return 2; // No deserving employees
        }
    }
As soon as the throw happens, all three employees need to be destroyed.  But
the catch(Employee e) has to catch whichever employee was thrown.  So the
throw copies the thrown employee somewhere, and then all three original
employees are deleted.  The catch() expression gets this special copy,
which is destroyed when catch() is through.

If you implement CException::CException(const CException&), then your example
will work correctly.  Alternately, change your try/catch code:
    try {
        if (1)                // check for "exception" condition
            throw new CException(new CMyReport ("hello catch",13));
            //    ^^^
    }
    catch (CException *e) {
        CReportSink s;
        e->Report (s);
        delete e;
    }
This also constructs a CException, with operator new.  Then it throws a
CException* instead of throwing a CException.  Copying a pointer does not
alter the pointed-to object, so when the catch gets the copied pointer,
it can use the same constructed CException that was created in the throw
statement.  Of course, deleting the CException must be done manually...

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/   Now offering spam-free web-based newsreading
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1998/06/11
Raw View
haberg@xxx.matematik.su.se (Hans Aberg) writes:

|>  In article <357d0c28.0@news.businessnet.dk>, "Albrecht Reimann"
|>  <NOSPAMare@basilproducts.dk> wrote:
|>
|>    You will have to do your debugging yourself -- I can only come up with a
|>  suggestion what to search for:
|>
|>  >The try/catch:
|>  >
|>  >try {
|>  >    if (1)                // check for "exception" condition
|>  >        throw CException(new CMyReport ("hello catch",13));
|>  >}
|>  >catch (CException & e) {
|>  >    CReportSink s;
|>  >    e.Report (s);
|>  >}
|>
|>    But possibly you should have:
|>
|>  catch (CException & e) {
|>      CReportSink* s;
|>      e.Report (*s);
|>  }
|>
|>    Because otherwise you call "s" as automatic variable, and the virtual
|>  information is lost.

This is ridiculous.  The Report function takes a reference, so full
polymorphism is retained, regardless of the storage class of the
operand.

--
James Kanze    +33 (0)1 39 23 84 71    mailto: kanze@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient   e objet --
              -- Beratung in objektorientierter Datenverarbeitung


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1998/06/12
Raw View
AllanW@my-dejanews.com writes:

|>  In article <357d0c28.0@news.businessnet.dk>,
|>    "Albrecht Reimann" <NOSPAMare@basilproducts.dk> wrote:
|>  >
|>  > // The exception holds a report with a description of the exception
|>  > class CException {
|>  > public:
|>  >     CException (CReport * aReport) {
|>  >         info = aReport;
|>  >     };
|>  >     CException (const CException & org) {
|>  >         assert (false);    // I don't want to provide a copy constructor,
|>  *** Why not?
|>
|>  > ... (I never reach here)
|>  *** Beg to differ.
|>
|>  >     };
|>  >     virtual ~CException (void) {
|>  >         if (info)
|>  >             delete info;
|>  >     };
|>  >
|>  >     CReport * getInfo (void) {
|>  >         return info;
|>  >     };
|>  >     unsigned Report (CReportSink & aSink) {
|>  >         info->doReport (aSink);
|>  >     };
|>
|>  You must have inserted the assert() for illustrative purposes only.  If you
|>  had left it in and enabled asserts, you would see that it was being hit!

Not necessarily -- the compiler is free to optimize the copy out.  (From
the symptoms he describes, however, I don't think it is, and that you
are right.)

--
James Kanze    +33 (0)1 39 23 84 71    mailto: kanze@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient   e objet --
              -- Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Albrecht Reimann" <NOSPAMare@basilproducts.dk>
Date: 1998/06/12
Raw View
>>     CException (const CException & org) {
>>         assert (false);    // I don't want to provide a copy constructor,
>*** Why not?
I did'nt want to cope with reference counting on CReport's, but, as I see
now, I have to !
>
>> ... (I never reach here)
>*** Beg to differ.
But true anyway. Thanks for your explanation, why I it should be called,
maybe the compiler optimizes the copy-ctor away, when throwing "anonymous"
objects, like in throw (CException (xyx))




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Albrecht Reimann" <NOSPAMare@basilproducts.dk>
Date: 1998/06/08
Raw View
In order to decouple exception handling, exception description, and
exception reporting, I use a three-fold exception object structure:
1. CException is a basic exception class, which holds a pointer to a
2. CReport, which contains an situation-dependent error description, and a
    virtual reporting method, which is used by a
3. CReportSink object to pass this description ahead to the appropriate
reporting
    channel (e.g. OLE IErrorInfo, Win/NT event log, message box, etc.).

This way, I can still select the appropriate exception handling using
specialized
CException classes and corresponding catch()es, I can pass specialized
descriptions
for my exceptions, and I can pass these descriptions to specialized
reporting channels.

My problem is: I throw a simple exception with a specialized CMyReport.
Then I catch a reference to this exception, but when I extract the
report pointer, it turned to be a simple CReport object. My compiler (VC++5)
simply replaces
the __vfptr of CMyReport with a one for CReport, just before entering the
catch() block.
Do I do something wrong, is this a compiler bug, or is it a special
Microsoft  feature ?

Best regards
Albrecht




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: haberg@xxx.matematik.su.se (Hans Aberg)
Date: 1998/06/08
Raw View
In article <357bbc65.0@news.businessnet.dk>, "Albrecht Reimann"
<NOSPAMare@basilproducts.dk> wrote:

>1. CException is a basic exception class, which holds a pointer to a
>2. CReport, which contains an situation-dependent error description
...
>My problem is: I throw a simple exception with a specialized CMyReport.
>Then I catch a reference to this exception, but when I extract the
>report pointer, it turned to be a simple object. My compiler (VC++5)
>simply replaces
>the __vfptr of CMyReport with a one for CReport, just before entering the
>catch() block.
>Do I do something wrong, is this a compiler bug, or is it a special
>Microsoft  feature ?

  Since you do not include any code, it is impossible to say if it is
someting wrong with it.

  But as your class CException contains a pointer to CReport which somehow
neglects the additional structure of a derived object, it sounds as if you
have forgotten to put in the correct copy constructor somewhere (perhaps
in the class CMyReport).

  You could also try an intrusive version, deriving CReport from
CException, and catching with "catch (CException& ex)".

  Hans Aberg   * Anti-spam: Remove "xxx." from email address.
               * Email: Hans Aberg <mailto:haberg@xxx.member.ams.org>
               * Home Page: <http://www.matematik.su.se/~haberg/>
               * AMS member listing: <http://www.ams.org/cml/>
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]