Jump to content
  • Advertisement
Sign in to follow this  
Drakkcon

Try catch help

This topic is 4953 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Okay, so I'm defining the methods of class 'Image' in cImage.cpp, and I decide to use try-catch blocks. Inside each function I have a try block and if making the SDL_Surface fails I throw an error string (STL string, it's a class member) that contains information on what happened. Then after all the functions I have the catch block that writes the error to a file. I got compiler errors because my catch was apparently too many code blocks above my trys so I created intermediate catch blocks that threw to the final catch. Here is the code for that:
//Includes
#include "../headers/cImage.h"

namespace AS
{
    
  cImage::cImage()
  {
    this->Source = NULL;
    this->Dest = NULL;
  }
  
  cImage::cImage(string File, SDL_Surface *Dest)
  {
      if(!(this->Dest = Dest))
      {
        Error = "Invalid dest. surface initialized";
        throw (Error);
      }
      LoadFromFile(File);
  }
  
  cImage::cImage(SDL_Surface *Source, SDL_Surface *Dest)
  {
    try
    {
      if(!(this->Source = Source))
      {
        Error = "Invalid source surface initialized";
        throw (Error);
      }
      
      if(!(this->Dest = Dest))
      {
        Error = "Invalid dest. surface initialized";
        throw (Error);
      }
    }
    catch (string s)
    {
      throw (s);
    }
  }
  
  cImage::cImage(SDL_Surface *Source, SDL_Surface *Dest, int w, int h, int x, int y)
  {
    this->Dimensions.w = w;
    this->Dimensions.h = h;
    this->Dimensions.x = x;
    this->Dimensions.y = y;
    
    try
    {
      if(!(this->Source = Source))
      {
        Error = "Invalid source surface initialized";
        throw (Error);
      }
      
      if(!(this->Dest = Dest))
      {
        Error = "Invalid dest. surface initialized";
        throw (Error);
      }
    }
    
    catch(string s)
    {
      throw(s);
    }
  }
  
  void cImage::Draw()
  {
    SDL_BlitSurface(Source, &Dimensions, Dest, &Location);
  }
  
  void cImage::Draw(int x, int y)
  {
    SetLocation(x, y);
    SDL_BlitSurface(Source, &Dimensions, Dest, &Location);
  }
  
  void cImage::SetSource(SDL_Surface *Source)
  {
    try
    {
      if(!(this->Source = Source))
      {
        Error = "Invalid source surface initialized";
        throw (Error);
      }
    }
    
    catch(string s)
    {
      throw(s);
    }
  }
  
  void cImage::SetDest(SDL_Surface *Dest)
  {
    try
    {
      if(!(this->Dest = Dest))
      {
        Error = "Invalid dest. surface initialized";
        throw (Error);
      }
    }
    
    catch(string s)
    {
      throw(s);
    }
  }
  
  void cImage::LoadFromFile(string FileName)
  { 
    //Turn the filename into a character array from a string
    char *ConvertedFileName;
    stringstream stream(FileName);
    stream >> ConvertedFileName;
    //load the BMP file
    this->Source = SDL_LoadBMP(ConvertedFileName); 
    
    try
    {
      if(Source == NULL)
      Error = "Invalid bitmap file.";
      throw (Error);
    }
    
    catch(string s)
    {
      throw(s);
    }
  }
  
  void cImage::SetDimensions(int w, int h, int x, int y)
  {
    this->Dimensions.w = w;
    this->Dimensions.h = h;
    this->Dimensions.x = x;
    this->Dimensions.y = y;
  }
  
  void cImage::SetLocation(int x, int y)
  {
    this->Location.x = x;
    this->Location.y = y;
  }
  
  //Catch Block
  catch (string)
  {
    fstream ErrorFile("ErrorLog.txt", ios::out);
    ErrorFile << string << endl << "-------------------------------" << endl;
    ErrorFile.close();
  }
    
} //End Namespace AS


I get the syntax error 'syntax error before catch' that directs me to the final catch block. How should I handle try catch in this situation? Also, in the catch block is there a way I could call the destructor (not implemented yet) before I quit? Thanks for any help.

Share this post


Link to post
Share on other sites
Advertisement
You could structure it like this:
try{
// Make some error
throw std::string("Some error!");
}
catch(std::string error){
std::cout << error;
}


... Also....


// This:

cImage::cImage(SDL_Surface *Source, SDL_Surface *Dest)
{
try
{
if(!(this->Source = Source))
{
Error = "Invalid source surface initialized";
throw (Error);
}

if(!(this->Dest = Dest))
{
Error = "Invalid dest. surface initialized";
throw (Error);
}
}
catch (string s)
{
throw (s);
}
}

// Should be:
cImage::cImage(SDL_Surface *Source, SDL_Surface *Dest)
{
if(!(this->Source = Source))
throw std::string("Invalid source surface initialized");


if(!(this->Dest = Dest))
throw std::string("Invalid dest. surface initialized");

}

// Then when you are working with making the images and stuff
// just make sure you surround them in a try catch block:

try {
cImage* image = new cImage(source, dest);
}
catch(std::string error){
// Caught the error - failed loading?
}




... But of course you should create derived error classes from std::exception.

Share this post


Link to post
Share on other sites
First of all, why are you surrounding your code with try/catch blocks, which promptly rethrow the error? Don't, it's a silly waste of code.

Secondly, you really should be throwing a type derived from std::exception. It's a much better practice than throwing around strings, also tends to mean that when someone else uses or looks at the code, it will make much more sense.

As for the error: you have a catch block with no try block.

Share this post


Link to post
Share on other sites
Quote:

First of all, why are you surrounding your code with try/catch blocks, which promptly rethrow the error? Don't, it's a silly waste of code.

That's the problem, I don't want to duplicate my error code for each function and I don't know how to elegantly make all my code go to one catch block. How do I do that? Also, could you show me how you would derive from std::exception? I've never done that before and don't really know why I would want to.

Share this post


Link to post
Share on other sites

//Includes
#include "../headers/cImage.h"

namespace AS
{
class ImageException : std::exception {
public:
ImageException(std::string const& error) : std::exception(error.c_str()) {}
};

cImage::cImage()
{
this->Source = NULL;
this->Dest = NULL;
}

cImage::cImage(string File, SDL_Surface *Dest)
{
if(!(this->Dest = Dest))
{
throw ImageException("Invalid dest. surface initialized");
}
LoadFromFile(File);
}

cImage::cImage(SDL_Surface *Source, SDL_Surface *Dest)
{
if(!(this->Source = Source))
{
throw ImageException("Invalid source surface initialized");
}

if(!(this->Dest = Dest))
{
throw ImageException("Invalid dest. surface initialized");
}
}

cImage::cImage(SDL_Surface *Source, SDL_Surface *Dest, int w, int h, int x, int y)
{
this->Dimensions.w = w;
this->Dimensions.h = h;
this->Dimensions.x = x;
this->Dimensions.y = y;

if(!(this->Source = Source))
{
throw ImageException("Invalid source surface initialized");
}

if(!(this->Dest = Dest))
{
Error = "Invalid dest. surface initialized";
throw (Error);
}
}

void cImage::Draw()
{
SDL_BlitSurface(Source, &Dimensions, Dest, &Location);
}

void cImage::Draw(int x, int y)
{
SetLocation(x, y);
SDL_BlitSurface(Source, &Dimensions, Dest, &Location);
}

void cImage::SetSource(SDL_Surface *Source)
{
if(!(this->Source = Source))
{
throw ImageException("Invalid source surface initialized");
}
}

void cImage::SetDest(SDL_Surface *Dest)
{
if(!(this->Dest = Dest))
{
throw ImageException("Invalid dest. surface initialized");
}
}

void cImage::LoadFromFile(string FileName)
{
//Turn the filename into a character array from a string
char *ConvertedFileName;
stringstream stream(FileName);
stream >> ConvertedFileName;
//load the BMP file
this->Source = SDL_LoadBMP(ConvertedFileName);

if(Source == NULL) {
throw ("Invalid bitmap file.");
}
}

void cImage::SetDimensions(int w, int h, int x, int y)
{
this->Dimensions.w = w;
this->Dimensions.h = h;
this->Dimensions.x = x;
this->Dimensions.y = y;
}

void cImage::SetLocation(int x, int y)
{
this->Location.x = x;
this->Location.y = y;
}
}

///Sample usage:
try {
std::auto_ptr<AS::cImage> img(new AS::cImage());
img->LoadFromFile("file that can't be found");
} catch(AS::ImageException& exception) {
std::cout<<exception.what();
}




When you throw an exception, it will automatically propagate up the call stack until it encounters a catch block that will handle it. This means that if any of those functions throws, it will work it's way up the call stack until it gets to my catch block. This is the entire point of exceptions, it simplifies error handling. Otherwise it would be no better than C error handling (return -1, test for -1, return -1, etc)

I should note that the exception class SHOULD be in the header, not in the source file, so that code that uses cImage can see the exception class.

Share this post


Link to post
Share on other sites
Thank you very much Washu, this will greatly improve my code.

Just a question though, is there any way to put the catch block in the class implementation instead of relying on the user to create one?

Share this post


Link to post
Share on other sites
Sure, but why would you? It is the users responsibility to catch and handle the errors, as they know how they wish the application to respond. If they don't handle it, well, they will find out pretty soon that they need to.

Share this post


Link to post
Share on other sites
Thanks, I understand now.

What more would I have to do to get your exception class to work though? I've been fiddling with it, but std::excpetion::exception() (constructor) doens't take any arguments, so I don't know why your initializer list is set up to send a c-string. Is my compilers' STL implementation faulty?

Here's how it's set up:

class exception
{
public:
exception() throw() { }
virtual ~exception() throw();
/** Returns a C-style character string describing the general cause
* of the current error. */

virtual const char* what() const throw();
};






It's constructor doesn't actually do anything, and I don't see how I would use it.

Oh, and when I try to compile it gives me a dozen errors saying that I have to have one catch per try block, so it won't work. That's why I had the original system.

[Edited by - Drakkcon on March 29, 2005 5:41:57 PM]

Share this post


Link to post
Share on other sites
Nevermind, problem solved. I learned a new thing today: don't use try blocks in a file without a catch (I thought that in order to use throw you had to use try but instead it's in order to use catch, stupid me). Thanks everyone, all.rate++.
Still having trouble with the exception class though.

Share this post


Link to post
Share on other sites
forget it. I inherited from runtime_error instead of Exception. This solved my problem! Thanks for the help washu.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!