CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Mar 2011
    Posts
    13

    custom exception class destructor

    I have this code that creates a custom exception class which has private data members of type const char*. I want to delete those pointers in the destructor, but since the exception is thrown inside the Price object's code, the destructor seems to be getting called before catch block in the main function. I'm new to this, so if anyone could point me in the right direction, I'd really appreciate it.

    Code:
    //CCException.h
    #pragma once
    #include <iostream>
    using namespace std;
    
    class CCException
    {
    public:
    	CCException(const char* m, const char* f);
    	~CCException(void);
    	void PrintMessage() const;
    private:
    	 const char* message;
    	 const char* function;
    };
    Code:
    //CCException.cpp
    #include "CCException.h"
    
    
    CCException::CCException(const char* m, const char* f)
    {
    	message = m;
    	function = f;
    }
    
    
    CCException::~CCException(void)
    {
    	//delete [] message;
    	//message = NULL;
    }
    
    void CCException::PrintMessage() const
    {
    	cout <<"Error in "<< function << ": " << message << endl;
    }
    Code:
    //price.h
    #pragma once
    #include "CCException.h"
    
    class Price
    {
    public:
    	const enum Term {Short, Medium, Long};
    	Price(const int &n);
    	~Price(void);
    	const double getPrice(const int &i) const;
    	void setPrice(const double &d, const int &i);
    	void setMR(const double &d, const Term &t);
    	void setVol(const double &d, const Term &t);
    private:
    	double* forwardcurve;
    	double a[3];
    	double v[3];
    	int count;
    };
    Code:
    //price.cpp
    #include <time.h>
    #include "price.h"
    #include "CCException.h"
    
    Price::Price(const int &n)
    {
    	count = n;
    	for (int i = 0; i < 3; i++) {
    		a[i]=0;
    		v[i]=0;
    	}
    	srand(time(NULL));
    	forwardcurve = new double[n];
    	for (int i = 0; i < n; i++) {
    		forwardcurve[i] = (double)(rand() % 1000) / 100;
    	}
    }
    
    Price::~Price(void)
    {
    	delete [] forwardcurve;
    	forwardcurve = NULL;
    }
    
    const double Price::getPrice(const int &i) const
    {
    	if (i >= 0 && i < count)
    		return forwardcurve[i];
    	else {
    		throw CCException("Index out of range.","Price::GetPrice");
    	}
    }
    
    void Price::setMR(const double &d, const Term &t)
    {
    	if (d >= 0)
    		a[(int)t] = d;
    }
    
    void Price::setVol(const double &d, const Term &t)
    {
    	if (d >= 0)
    		v[(int)t] = d;
    }
    
    void Price::setPrice(const double &d, const int &i)
    {
    	if (d > 0 && i < count)
    		forwardcurve[i] = d;
    	else{
    		throw CCException("Index out of range.","Price::SetPrice");
    	}
    }
    Code:
    //main.cpp
    #include "price.h"
    #include "CCException.h"
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    	int n = 20;
    	Price p = Price(n);
    	char buffer[100];
    
    	try {
    
                    //This throws an exception when n=20.
    		for (int i = 0; i < n+1; i++)
    			cout << p.getPrice(i) << endl;
    	}
    
    	//Error catching code.
    	catch (const char *e){
    		cout << e << endl;
    	}
    	catch(const CCException e){
    		e.PrintMessage();
    	}
    	catch(...){
    		cout << "Unknown Error"<<endl;
    	};
    
    	cin.getline(buffer,100);
    };

  2. #2
    Join Date
    Aug 2008
    Posts
    902

    Re: custom exception class destructor

    I think it is generally considered bad practice to create your own exception classes from scratch, as opposed to publicly deriving them from std::exception. You should probably consider using std::string objects instead of char*s. Also, n being equal to 20 hardly seems like an exceptional case. You should make sure you are using exceptions for the right reasons.

    The other mistake you are making is trying to delete the char* in the first place. You only delete things that are created with new.
    Last edited by Chris_F; March 1st, 2011 at 09:45 PM.

  3. #3
    Join Date
    Mar 2011
    Posts
    13

    Re: custom exception class destructor

    Thanks for all of the advice. This isn't really anything I'm going to actually use, I'm just sort of testing out what everything in C++ does.

  4. #4
    Join Date
    Mar 2011
    Posts
    13

    Re: custom exception class destructor

    Quote Originally Posted by Chris_F View Post
    Also, n being equal to 20 hardly seems like an exceptional case. You should make sure you are using exceptions for the right reasons.
    I mistyped. I meant when i = 20. i = 20 is an exceptional case because the forwardcurve array only has 20 elements, so trying to get forwardcurve[20] would be out of the bounds. Is it not good practice to throw exceptions in this case? What should one do?

    Thanks again!
    Last edited by positivelyskewed; March 2nd, 2011 at 12:57 AM.

  5. #5
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: custom exception class destructor

    Quote Originally Posted by positivelyskewed View Post
    I have this code that creates a custom exception class which has private data members of type const char*. I want to delete those pointers in the destructor, but since the exception is thrown inside the Price object's code, the destructor seems to be getting called before catch block in the main function. I'm new to this, so if anyone could point me in the right direction, I'd really appreciate it.
    That's because you catch by value and your exception class is not safely copyable. You should always catch by const reference and you should always make your classes safely copyable or disable copying by declaring the copy constructor and copy assignment operator private (or use the = delete syntax from C++0x if your compiler supports this).
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  6. #6
    Join Date
    Apr 1999
    Posts
    27,449

    Re: custom exception class destructor

    Quote Originally Posted by positivelyskewed View Post
    Thanks for all of the advice. This isn't really anything I'm going to actually use, I'm just sort of testing out what everything in C++ does.
    Then you should learn the proper practices. A C++ program can be written elegantly, or without any coherence or thought. Either case will produce a compilable program that can work, but what about maintenance, enhancements, and debugging issues?

    I want to delete those pointers in the destructor,
    Learn RAII and use objects that are smart enough to copy and destroy themselves automatically.

    For example, a std::string instead of char* would have alleviated the problem, since a std::string knows how to copy itself and destroy itself automatically without you having to write any code. A char* is just a "dumb" pointer that you now have to manage.

    Here is a simplified version of the mess you got yourself into with your exception class:
    Code:
    class foo
    {
         char *ptr;
    
         public:
         foo()
         {
               ptr = new char [10];
         }
    
         ~foo()
          { 
              delete [] ptr;
          }
    };
    
    int main()
    {
       foo f1;
       foo f2 = f1;
       foo f3;
       f3 = f1;
    }
    The code above has a memory leak, and a triple deletion error, where you're deallocating the same pointer three times on exit.

    If this class were written to take care of all of these problems, the hard way to do it would be this:
    Code:
    #include <cstring>
    
    class foo
    {
         char *ptr;
    
        public:
        foo()
        {
               ptr = new char [10];
        }
    
         ~foo()
         { 
             delete [] ptr;
         }
    
         foo(const foo& rhs)
         {
            ptr = new char[10];
            memcpy(ptr, rhs.ptr, 10);
         }
    
         foo& operator =(const foo& rhs)
         {
              if ( &rhs != this )
              {
                  char *temp = new char [10];
                  memcpy( temp, rhs.ptr, 10 );
                  delete [] ptr;
                  ptr = temp;
              }
              return *this;
         }
    };
    Now the main() program will work correctly.

    Or you can do it the easy way:
    Code:
    #include <string>
    
    class foo
    {
        std::string ptr;
    
        public:
        foo() : ptr(10, '\0') { }
    };
    The code above essentially does the same thing as the code that had the char*. Now which one is easier to maintain? But the more important question is this -- why is the second code easier to maintain? What in the second example makes a user-defined destructor, assignment operator, and copy constructor unnecessary?

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; March 2nd, 2011 at 05:59 AM.

  7. #7
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: custom exception class destructor

    Quote Originally Posted by D_Drmmr View Post
    That's because you catch by value and your exception class is not safely copyable. You should always catch by const reference and you should always make your classes safely copyable or disable copying by declaring the copy constructor and copy assignment operator private (or use the = delete syntax from C++0x if your compiler supports this).
    Technically, even when you catch an exception by reference, the compiler still uses pass by value. This is due to the fact that a catch never returns control to the caller, and is thus responsible for clean-up.

    That said, when you catch by value, chances are you copy the the exception... twice.

    Meyers gives all the details in one of his books, can't remember which. Cline also states in his FAQ, that an exception MUST be copy constructible... even if the copy constructor is never called.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  8. #8
    Join Date
    Mar 2011
    Posts
    13

    Re: custom exception class destructor

    Quote Originally Posted by Paul McKenzie View Post
    Then you should learn the proper practices. A C++ program can be written elegantly, or without any coherence or thought.
    Exactly what I'm trying to figure out! Thanks for the tips. I appreciate all of the criticism because I really want to learn how to write good code, not just code that works.

  9. #9
    Join Date
    Mar 2011
    Posts
    13

    Re: custom exception class destructor

    Quote Originally Posted by Paul McKenzie View Post
    What in the second example makes a user-defined destructor, assignment operator, and copy constructor unnecessary?
    Quote Originally Posted by Paul McKenzie View Post
    a std::string knows how to copy itself and destroy itself automatically without you having to write any code.
    That was a very useful example. I actually didn't realize that the first code had that triple deletion thing going on. Looks like I have a lot of reading to do...
    Last edited by positivelyskewed; March 2nd, 2011 at 02:08 PM.

  10. #10
    Join Date
    Apr 1999
    Posts
    27,449

    Re: custom exception class destructor

    Quote Originally Posted by positivelyskewed View Post
    Exactly what I'm trying to figure out! Thanks for the tips. I appreciate all of the criticism because I really want to learn how to write good code, not just code that works.
    Well, with C++, you start out with components that work (for example std::string), and put together a program from workable smaller parts. At least, that is the modern way to learn C++. Unfortunately, most courses do not teach C++ this way, and instead teach 'C' programming with some C++ syntax thrown in.

    You still have to write the logic to put these components together to create a program, but the foundational blocks you're using must be sound. With the example you had, you were struggling with string data, when there was no need to -- C++ handles string data easily if you use the right standard components.

    The same thing with dynamic arrays, linked lists, and other aspects. There is no need to write your own if the ones available to you from the standard library (vector, list, deque, set, map, etc.) are adequate (and for a vast majority of C++ programmers, they are adequate, if not superior to whatever the programmer could write themselves). The goal being that you don't want to be in the maintenance business maintaining this "low-level" code, which means spending time debugging it if something is wrong. Instead, you give more time in developing the program you're creating, and not creating mini linked-list or string classes before even getting started.

    So if you use the jigsaw puzzle as an analogy to writing a program, the C++ thinking shifts from having to create each jigsaw puzzle piece (your attempt at using char*) into how to efficiently and elegantly put the jigsaw puzzle together from the pieces that are already created.

    You will get to the point where you may have to write code such as the first example of the foo() class, but make those times rare. I can't remember the last time I had to write code like the first foo() class in a real application, and I've been doing this for over 20 years now.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; March 2nd, 2011 at 02:20 PM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured