Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Dudas con una funcion y el uso de try catch (https://www.clubdelphi.com/foros/showthread.php?t=87347)

aguml 18-12-2014 11:08:06

Dudas con una funcion y el uso de try catch
 
Hola amigos, ahora estoy ya intentando mejorar la aplicación y en vez de usar (nothrow) quiero usar try catch y en la siguiente funcion lo hago pero no se si hace lo que yo quiero ¿podeis decirme si se me pasa algo y ayudarme a corregirla?

Código PHP:

int __fastcall TForm2::CrearDivisionesImagen(TStringList *DivisionesAnsiString RutaActualint maxHeightint maxWidth)
{
   
int auxMaxHeightauxMaxWidthdivisiones 0;

   if(
maxHeight == || maxWidth == 0)
   {
      
MessageBox(Application->Handle"El tamaño del papel seleccionado no es válido. Usa A5, A4, o A3""Error"MB_OK |MB_ICONERROR MB_APPLMODAL);
      
divisiones = -3;
   }
   else
   {
      try
      { 
//Aqui divido la imagen en archivos mas pequeños
         
Graphics::TBitmap *bmp = new Graphics::TBitmap();

         try
         {
            
TRect src;
            
int i1,i2,j1,j2;

            
// Cargar imagen
            
bmp->LoadFromFile(RutaActual);

            
// Recorrer y crear las imagenes pequeñas
            
for(int i 1auxMaxWidth bmp->WidthauxMaxWidth 0;i++, auxMaxWidth -= maxWidth)
            {
               
i1 = (i-1) * maxWidth;
               
i2 maxWidth;
               for(
int j 1auxMaxHeight bmp->HeightauxMaxHeight 0j++, auxMaxHeight -= maxHeight)
               {
                  try
                  {
                     
// nueva imagen
                     
Graphics::TBitmap *bmpij = new Graphics::TBitmap();

                     
// proteccion
                     
try
                     {
                        
bmpij->Width maxWidth;
                        
bmpij->Height maxHeight;
                        
j1 = (j-1) * maxHeight;
                        
j2 maxHeight;
                        
src Rect(i1,j1,i2,j2);

                        
// Mismo formato
                        
bmpij->PixelFormat bmp->PixelFormat;

                        
// Copiar a la imagen pequeña el "trozo" correspondiente
                        
bmpij->Canvas->CopyRect(bmpij->Canvas->ClipRectbmp->Canvassrc);

                        
//Guardo las rutas de las divisiones en RutasDivisiones
                        
Divisiones->AddAnsiString().sprintf("%soutput_%d_%d.bmp"ExtractFilePath(Application->ExeName), i,j));

                        
// Grabar
                        
bmpij->SaveToFile(Divisiones->Strings[Divisiones->Count-1]);

                        
AsignarImagen(Divisiones->Strings[Divisiones->Count-1]);
                        
delete bmpij;
                        
bmpij NULL;
                        
divisiones++;
                     }
                     catch(...)
                     {
                        
delete bmpij;
                        
delete bmp;
                        
Application->MessageBoxA("Hubo un error al dividir las imagenes. Error desconocido. La aplicación se cerrará.""Error"MB_OK MB_ICONERROR);
                        
divisiones = -2;
                     }
                  }
                  catch(...)
                  {
                     
Application->MessageBoxA("Hubo un error al dividir las imagenes. No hay memoria suficiente.\nLa aplicación se cerrará.""Error"MB_OK MB_ICONERROR);
                     
delete bmp;
                     
divisiones = -1;
                  }
               }
            }
         }
         catch(...)
         {
            
delete bmp;
            
Application->MessageBoxA("Hubo un error al dividir las imagenes. Error desconocido. La aplicación se cerrará.""Error"MB_OK MB_ICONERROR);
            
divisiones = -2;
         }
         
delete bmp;
      }
      catch(...)
      {
         
Application->MessageBoxA("Hubo un error al dividir las imagenes. No hay memoria suficiente.\nLa aplicación se cerrará.""Error"MB_OK MB_ICONERROR);
         
divisiones = -1;
      }
   }
   return 
divisiones;


La idea es que divida la imagen y eso ya lo hacia pero ahora lo que quiero es que si hay cualquier error la funcion termine y retorne el valor que asigno a "divisiones", esté donde esté en la funcion, da igual que esté dentro de un for o no, tiene que salir retornando el valor que asigno a "divisiones". Los mensajes que pongo no van ahi sino que lo gestiono al salir de la aplicacion dependiendo del retorno pero los he puesto ahi para que lo veais mas claro.

aposi 18-12-2014 12:30:33

hola,
has probado de poner un return divisiones enla ultima linea de cada catch ?

aguml 18-12-2014 12:50:33

es que he leido que no es una buena practica poner un return al final de un catch.
Aquí lo que leí: http://www.marteens.com/trick0d.htm
Si alguien puede aclararme las ideas al respecto...

ecfisa 18-12-2014 13:05:11

Hola aguml.

No he probado el código, pero en apariencia es correcto. Lo único que me gustaría comentarte es una alternativa que te evitará el doble llamado al operador delete():
Código PHP:

  ...
  
Graphics::TBitmap *bmp = new Graphics::TBitmap();
  
__try {
    try {
    
// acciones que pueden fallar
    
}
    catch(...) {
      
// Gestión del error
      
Application->MessageBoxA("Hubo un error al dividir las imagenes. Error desconocido. La aplicación se cerrará.""Error"MB_OK MB_ICONERROR);
      
divisiones = -2;
    }
  }
  
__finally {
   
// Este bloque se ejecutará tanto si hubo error como si no.
    
delete bmp;
  }
  ... 

Saludos :)

aguml 18-12-2014 13:26:07

La verdad es que no se como acomodar lo que me pones "ecfisa". Otra cosa, cuando entro en el catch y ejecuto la ultima linea que está dentro del catch ¿ejecuta el return de la funcion? ¿que pasa al salir del catch?

ecfisa 18-12-2014 14:06:05

Cita:

Empezado por aguml (Mensaje 486794)
La verdad es que no se como acomodar lo que me pones "ecfisa".

Usa __try inmediatamente seguido a la creación de bmp. Dado que el bloque __finally se ejecutará siempre, evitarás de ese modo el cuádruple llamado a delete bmp que realizas en tu código.

Otro ejemplo:
Código PHP:

{
  
// Se solicita el recurso
  
TStringList *sl = new TStringList;
  
__try {
    try {
      
sl->LoadFromFile(PATH); // ruta al archivo (correcta o errónea)
    
}
    catch(...) {
      
// Se tratan los errores (si los hay)
      
ShowMessage("Error ...");
    }
  }
  
__finally {
    
// Se libera el recurso 
    
delete (sl);
  }


Cita:

Empezado por aguml (Mensaje 486794)
Otra cosa, cuando entro en el catch y ejecuto la ultima linea que está dentro del catch ¿ejecuta el return de la funcion?

Si.
Podes usar un breakpoint y ejecutar con F7 (o devolver un valor arbitrario) para comprobarlo.

Saludos :)

dec 18-12-2014 15:18:01

Hola,

Digo yo una cosa, ¿debe una función informar al usuario, directamente, de que se ha producido un error? ¿No debería más bien la función "levantar" la excepción, y, ser quien llame a dicha función quien avise del error al usuario si este lo ve necesario? Claro que podemos tratar excepciones en bloques de código fuera de funciones, y, ahí lo vería más lógico, pero, para mí que una función sólo debe levantar excepciones y no directamente mensajes de error.

¿Cómo lo véis vosotros? :)

ecfisa 18-12-2014 15:34:34

Hola dec.

Estoy totalmente de acuerdo con eso. El tratamiento de los mensajes de error debería realizarse aparte. En lo personal aprovecho el evento OnException para la personalización de los mismos.

Sólo quería señalarle a aguml, que se puede evitar la redundancia de declaraciones de liberaciones de recursos con la extensión de C++ Builder, __finally.

Saludos :)

ecfisa 18-12-2014 16:17:24

Hola.

Un ejemplo muuuy resumido ...
Código PHP:

void __fastcall TForm1::MyHandlerExcept(TObjectSenderExceptionE)
{
  
ShowMessage(E->Message "\n ( From MyHandlerExcept )");
};

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  
Application->OnException MyHandlerExcept;
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  
TStringList *sl = new TStringList;
  try {
    
sl->LoadFromFile("*:\uuuuu.uuu"); // forzar el error
  
}
  
__finally {
    
delete sl;
  }
}
... 

Saludos :)


La franja horaria es GMT +2. Ahora son las 05:12:45.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi