Vous êtes sur la page 1sur 18

DEV C++

ERRORES COMUNES DEL LENGUAJE C UTILIZANDO DEV C++ Y SUS POSIBLES SOLUCIONES.
Aqu tenemos los tres errores mas frecuentes de los principiantes de C utilizando Dev-C++ las cuales son:

Error: debido a que GCC requiere que TODAS las lneas terminen con el carcter de 'lnea nueva' (el generado por la tecla {ENTER})
Cdigo: "8:2 C:\Dev\User\C\Hello_world\HelloWorld.c [Warning] no newline at end of file" Solucin: la forma ms sencilla de solucionar este error es colocando el cursor de texto al final del archivo de cdigo fuente y despus de esto simplemente presionamos la tecla {ENTER}.

Error: No hay "pausa automtica" cuando se ejecuta una aplicacin de consola desde Dev-C++.
Por ejemplo este programa: Cdigo: #include <stdio.h> int main(void) { printf("Hola, Mundo\n"); return 0; } Aparece y desaparece en un instante. Esto se debe a que a diferencia de otros IDEs Dev-C++ no soporta la generacin automatica de esta pausa. La nica solucin es que los usuarios de este IDE hagan una peticion para que eventualmente se aada esta caracterstica. Una "solucin a medias" pero que funciona es utilizar la funcin getchar en esta forma: Cdigo: #include <stdio.h> int main(void) { printf("Hola, Mundo\n"); getchar(); return 0; }

Error: Dev-C++ no soporta (reconoce) las funciones como gotoxy y getch


Por ejemplo este programa: Cdigo: #include <stdio.h> #include <conio.h> int main() { gotoxy( 20, 10 ); printf( "Hola" ); getch(); return 0; } Al ser compilado genera este error: Cdigo: "[Linker error] undefined reference to `gotoxy'"

Esto se debe a que esa biblioteca debe instalarse aparte y como un "dev-pack". Para esto se debe estar conectado a Internet y en Dev-C++ se selecciona el menu "Tools" (Herramientas), "Check for updates/packages" (Verificar actualizaciones/paquetes). En ese cuadro de dialogo: 1) En "Select devpack server" seleccionamos como servidor a "devpacks.org Community Devpacks". 2) Le damos click al boton "Check for updates" ("Revisar si hay actualizaciones"). 3) Seleccionamos el devpack "CONIO" y le damos click al boton "Download selected" (descargar seleccionados). Despus de esto aparece otro cuadro de dialogo donde debemos darle click al boton "Install" (Instalar). Por ultimo debemos seleccionar el menu "Tools" (Herramientas), "Compiler options" (Opciones del compilador) y en el cuadro de texto "Adds these commands to the linker command line". Despus de esto el programa debe compilar correctamente.

Revisemos otros errores de los muchsimos que hay.


Error: pausar programa
Los principiantes cuando ejecutan el programa no pueden ver el resultado. Para evitarlo se puede aadir antes de return 0; la siguiente lnea: Cdigo: system("PAUSE");

Si esto no funciona prueba a aadir getch();" * Tomando en consideracin que este es el primer programa que compila el lector y que: A) system recurre a la librera de stdlib.h B) getch recurre a la librera de conio.h Seria mejor recomendar el uso de la funcin getchar ya que esta es la que requiere de menos cambios al codigo fuente: Cdigo: #include <stdio.h> int main() { printf("Hola mundo\n"); getchar(); /* pausa */ return 0; }

Error: Al definir la funcin Main


"int main()" Esta es una forma correcta de definir a la funcion 'main' pero seria incluso mejor utilizar la forma "int main(void)" ya que esta tambien es una forma correcta y algunos compiladores como Lcc-win32 y Pelles C al ser utilizados en su modo mas estricto "se quejan" de la forma "int main()".

Error: Impresin de comillas


"Printf: Imprimir en pantalla": Cita: Qu pasa si queremos imprimir el smbolo Comillas ( " ) en pantalla? Por ejemplo imaginemos que queremos escribir: Cdigo: Esto es "extrao"

El uso de caracteres como las vocales acentuadas o, como en este caso la '' puede resultar problematicos ya que no forman parte del cdigo ASCII sino del "Extended ASCII character set". Y debido a que los caracteres que componen este "character set" dependen de como este configurado el SO del lector seria mejor evitar los caracteres que no formen parte del juego de caracteres ASCII.

Error: Impresin de

"Printf: Imprimir en pantalla": "Esta contrabarra se usa en C para indicar al compilador que queremos meter smbolos especiales. Pero Y si lo que queremos es usar '\' como un carcter normal y poner por ejemplo Hola\Adis? Pues muy fcil, volvemos a usar '\': Cdigo: printf( "Hola\\Adis" ); y esta doble '\' indica a C que lo que queremos es mostrar una '\'." Seria bueno colocar despus de este prrafo una lista de los caracteres especiales en el lenguaje C y que deben ir precedidos por una '\': Cdigo: \a alert \b backspace \f formfeed \n newline \r carriage return \t horizontal tab \v vertical tab \\ backslash \? question mark \' single quote \" double quote alerta o campana retroceso ---??? nueva linea retorno de carro tabulador horizontal tabulador vertical diagonal invertida signo de interrogacion comilla sencilla comilla doble

Error: Retorno de Main


El valor de retorno de la funcion "main" seria mejor utilizar la forma: Cdigo: int main(void) { /* ... */ }

Nota: Hay una lista de las palabras reservadas o keywords, estas son segn el estandar ISO-C90: Cdigo: auto, double, int, struct, break, else, long, switch, case, enum, register, typedef, char, extern, return, union, const, float, short, unsigned, continue, for, signed, void, default, goto, sizeof, volatile, do, if, static, while, etc..

Error: Imprimir contenido de variables


Asignar valores a variables de tipo int, la primera llamada a la funcin printf tiene un error de sintaxis: Cdigo: prinft( "El valor inicial de x es %i\n, x" ); Debera ser: Cdigo: printf( "El valor inicial de x es %i\n", x );

Informacin importante.
1) En C los tipos utilizados para almacenar nmeros se conocen como tipos aritmticos y se dividen en dos grupos: tipos enteros y tipos de punto flotante. 2.1) Los tipos enteros son char, short int, int y long int. Los tipos short int y long int se pueden abreviar a solo short y long. 2.2) Los indicadores de signo signed y unsigned solo pueden aplicarse a los tipos enteros. El primero indica que el tipo puede almacenar tanto valores positivos como negativos y el segundo indica que solo se admiten valores no negativos, esto es, solo se admite el cero y valores positivos. 2.3) Si se declara una variable de tipo short, int o long sin utilizar un indicador de signo esto es equivalente a utilizar el indicador de signo signed. Por ejemplo: signed int i; int j; Declara dos variables de tipo signed int. 2.4) La excepcin es el tipo char. Cuando se declara una variable de tipo char sin utilizar un indicador de signo si esta variable es equivalente a signed char o a unsigned char depende del compilador que estemos utilizando. Por lo mismo si debemos tener total certeza de que nuestras variables de tipo char puedan almacenar (o no) valores negativos es mejor indicarlo explcitamente utilizando ya sea signed char o unsigned char. 2.5) El numero de valores posibles y nicos que pueden almacenarse en un tipo entero depende del numero de bits que lo componen y esta dado por la expresin 2^N donde N es el numero de bits. Por ejemplo si en nuestro caso el tipo

short esta compuesto por 16 bits el numero de valores posibles es 65,536. 2.6) En los tipos sin signo el valor mnimo que puede almacenarse es 0 y el mximo esta dado por 2^N - 1. 2.7) En los tipos con signo el valor mnimo esta dado por la expresin -(2^(N - 1) - 1) y el valor mximo por 2^(N - 1) - 1. Por ejemplo si en nuestro caso el tipo signed char esta constituido por 8 bits entonces su valor mnimo es -127 y su valor mximo 127.

2.8) El tipo short esta constituido por al menos 16 bits y el tipo long por al menos 32 bits. El tipo int "flota en medio" y usualmente tiene el mismo numero de bits que el tipo short o el tipo long. 2.9) El numero de bits que componen a los tipos short, int y long siempre cumple esta regla: short <= int <= long 2.10) El numero exacto de bits que componen a los tipos short, int y long depende de la implementacin (es la combinacion de software y hardware que estemos utilizando) que estemos utilizando. 2.11) El numero de bits por byte es usualmente 8 pero esto no esta garantizado, para conocer este valor podemos utilizar la macro CHAR_BIT que esta definida en limits.h 2.12) Los tipos enteros sin signo no pueden desbordarse. 2.13) Los tipos enteros con signo si pueden desbordarse y esto produce "undefined behaviour". En espaol: si una variable de tipo entero con signo se desborda cualquier cosa puede pasar: resultados incorrectos, el programa simplemente revienta, etc. 3.1) Los tipos de punto flotante son float, double y long double. 3.2) La relacion entre los tipos float, double y long double es: float <= double <= long double 3.3) Los rangos posibles de estos tres tipos depende de la implementacin pero los tres estn garantizados a poder almacenar numeros en el rango -10^37 a 10^37.

Error: Enteros double


Un ejemplo es donde se manejan nmeros de tipo double (un ejemplo es la constante PI 3.1416) seria mejor cambiar el tipo de las variables del tipo int al tipo double. Ejemplo: Cdigo: #include <stdio.h> int main(void) {

double radio; double perimetro; radio = 20.0; perimetro = 2.0 * 3.1416 * radio; printf("El permetro es: %f\n", perimetro); return 0; } Las constantes en base 10 (decimal) y sin fraccion ni exponente son de tipo signed int. Algunos ejemplos: Cdigo: a = 100; b = 200; c = 300; d = 400; NOTA: Para indicar de una forma explicita el tipo de una constante entera se pueden utilizar los sufijos 'U' y/o 'L' ya sea en minusculas o mayusculas. El primero indica que es un tipo sin signo (unsigned) y el segundo que es de tipo 'long int'. Algunos ejemplos: Cdigo: a = 100; /* 100 es de tipo signed int */ b = 200U; /* 200U es de tipo unsigned int */ c = 300L; /* 300L es de tipo signed long */ d = 400UL; /* 400UL es de tipo unsigned long */

Y que pasa si una constante "no cabe" en el tipo indicado? Supongamos que (en nuestro caso) el valor maximo que se puede almacenar en el tipo int es 32767 y (por poner un ejemplo) en un programa tenemos: Cdigo: int a = 32768; /* 32768 "no cabe" en un int */ Que es lo que sucede? Bueno, en realidad las constantes enteras *Y* en base 10 son del tipo mas pequeo que pueda almacenar el numero en cuestion y el tipo de la constante se selecciona en este orden: 1) int 2) long 3) unsigned long Debido a que en nuestro ejemplo 32768 no cabe en un int se revisa el tipo signed long y si en este tampoco cabe el tipo de la constante es unsigned long y si la constante en cuestion tiene uno de los dos sufijos 'U' o 'L' el tipo a utilizar se restringe (limite) y selecciona en este orden: A) En el caso de utilizar 'U': 1) unsigned int 2) unsigned long

B) En el caso de utilizar 'L': 1) signed long 2) unsigned long 2) Las constantes en base 10 y con un punto decimal y/o exponente son de tipo double. Algunos ejemplos: Cdigo: a = 100.0; /* 100.0 es de tipo 'double' */ b = 10E2; /* 10E2 es de tipo 'double' */ Las constantes de punto flotante son de tipo double a menos que se utilize uno de estos sufijos ya sea en minusculas o mayusculas: A) El sufijo 'F' indica que la constante es de tipo float. B) El sufijo 'L' indica que la constante es de tipo long double. Solo se debe utilizar uno de estos sufijos pero no ambos. Algunos ejemplos: Cdigo: a = 100.0F /* 100.0F es de tipo float */ b = 200.0 /* 200.0 es de tipo double */ c = 300.0L /* 300.0L es de tipo long double */

Observacion: En estos ultimos ejemplos y ejercicios no se utiliza la palabra reservada "return" para indicar el valor de retorno de la funcion "main" lo que puede ocasionar que algunos compiladores al ser utilizados en su modo mas estricto posible emitan una advertencia. Por lo mismo seria mejor utilizar la forma: Cdigo: /* ... */ int main(void) { /* ... */ return 0; }

Error : Errores de "Operadores lgicos" AND & OR.


1) Estos dos operadores garantizan el orden de evaluacion: primero se evalua el operando a su izquierda y solo despues de esto (y si es necesario) el operando a su derecha. 2) A estos dos operadores se les conoce como "operadores de corto circuito" o "short circuit operators" debido a la forma particular en la que operan: * En el caso del operador AND su resultado es 0 si la primera expresion es falsa (igual a 0), la segunda expresion no se evalua.

* En el caso del operador OR su resultado es 1 si la primera expresion es verdadera (diferente de 0), la segunda expresion no se evalua. Estos dos operadores son particularmente tiles cuando se debe evaluar (o no) una expresin dependiendo de la evaluacin de una expresin anterior. Por ejemplo supongamos que tenemos dos nmeros enteros (a y b) y tenemos que verificar si el primero (a) es un multiplo del segundo (b). Para esto solo tenemos que verificar si el modulo o residuo de la divisin de a entre b es igual a cero siempre y cuando b, para empezar, no sea igual a cero. Esto se puede implementar fcilmente con el operador lgico AND: Cdigo: if ((b != 0) && (a % b == 0)) /* b es multiplo de a */ Aqu el operador AND primero evala la expresin a su izquierda y solo si esta es verdadera (b es diferente de cero) se evala la expresin a su derecha (el residuo de a entre b es cero?).

Error: operadores sizeof


En los ejemplos de "Operadores Sizeof" se utiliza el indicador de tipo "%i" para imprimir el resultado del operador sizeof cuando el resultado de este es de tipo size_t. Ahora bien, lo nico que el estndar de C garantiza sobre este tipo (size_t) es que es un "tipo entero sin signo". Debido a esto lo mejor que se puede hacer en ISO-C90 para imprimir un valor de este tipo es convertirlo a unsigned long e imprimirlo como tal, por ejemplo: Cdigo: #include <stdio.h> int main(void) { printf( "Las variables tipo int ocupan %lu bytes\n", (unsigned long) sizeof(int) ); return 0; }

La mayora de los programas y ejercicios utilizan letras acentuadas y esto debera evitarse ya que el carcter que se presente en pantalla no esta garantizado. Bien podra ser la vocal acentuado o tal vez no. Recomendacion: Si se utiliza con la funcion scanf el indicador de tipo "%i" para convertir el contenido de la entrada estandar en un numero entero. Esto puede llevar a ciertos errores logicos debido a que este indicador acepta tanto numeros en base 10 como en base 8 (octal) y 16 (hexadecimal), Evitarlo para cometer errores

Por ejemplo si por accidente (o casualidad) se introduce el numero "0123" este no se interpreta (como es de esperarse) como un numero decimal sino como un numero octal. Cdigo: Introduce un numero: 0123 Has tecleado el numero: 83 Por todo esto me parece mejor utilizar el indicador de tipo "%d" ya que este solo acepta numeros en base 10. Ahora bien cuando se utiliza la funcion printf para enviar el texto "Introduce ..." a la salida estandar. Debido a que esta cadena no termina con el caracter '\n' no se puede tomar por garantizado que el texto se envie inmediatamente a nueva linea (stdout). Para estar seguros de que esto asi suceda debemos utilizar: Cdigo: fflush(stdout); Inmediatamente despues de la llamada a printf. O quizs en este ejemplo e error puede ser que falte la directiva:

#include <conio.h> Error: La variable "letra" utilizada para almacenar el valor de retorno de las funciones getch y getche se declara como tipo "char" cuando deberia ser de tipo "int".

Error cunado se utiliza "If",


Cunado se utiliza "If",este se enva mediante la funcion printf una cadena a la salida estndar, esa cadena no esta garantizada a presentarse antes de que se pida un numero en cuestion (mediante la funcion scanf). Para asegurarnos de que esto suceda se debe vaciar el bufer de la salida estandar mediante la funcion fflush: Cdigo: #include <stdio.h> int main(void) { int num; printf("Introduce un nmero "); fflush(stdout); scanf("%i", &num); if (num == 10){ printf("El nmero es correcto\n"); } return 0; } Este error se repite en varios de los programas de ejemplo de libros "If - Else" e "if else if".

Error lgico: considerando la explicacion "else if":


Cdigo: else if ( a>10 && a<100 ) Debera utilizar los operadores "mayor o igual que" (el operador '>=') y el operador menor o igual que (el operador '<='): Cdigo: else if (a >= 10 && a <= 100) Un error es que se debera indicar de una forma explicita que solo pueden utilizarse como condiciones las expresiones cuyo resultado sea de algun tipo entero como char, int, long, etc., por ejemplo esta expresion no seria valida como una condicion: Cdigo: 1.0 + 1.0 Ya que ambos operndos y el resultado de la expresin son de tipo 'double'.

Error lgico: if, else


En el segundo ejemplo de este capitulo el bloque if .. else en la funcion 'compara': Cdigo: if (a > b) printf("%i es mayor que %i\n" , a, b); else printf("%i es mayor que %i\n", b, a); Debera ser: Cdigo: if (a > b) printf("%i es mayor que %i\n" , a, b); else if (b > a) printf("%i es mayor que %i\n", b, a); else printf("%i es igual que %i\n", a, b);

Error logico: No utilizar operadores lgicos.


Cdigo: scanf("%i %i", num1, num2); Deberia ser: Cdigo:

scanf("%i %i", &num1, &num2); Al llamar a la funcion printf el indicador de tipo "%p" se utiliza para imprimir un valor de tipo "void *". Debido a esto cuando se llama a esa funcion para imprimir el valor de un puntero este debe ser convertido al tipo "void *" mediante una conversion explicita o casting.

Error en Arrays
Seria bueno aclarar que estas listas solo pueden consistir de valores literales para no cometer errores, por poner un ejemplo: Cdigo: int array[3] = {1, 2, 3}; y constantes simbolicas definidas mediante la directiva "define":

Cdigo: #define ELEMENTOS 24 Cdigo: #include <stdio.h> int main(void) { int hora; int temperaturas[] = {15, 18, 20, 23, 22, 24, 22, 25, 26, 25, 24, 22, 21, 20, 18, 17, 16, 17, 15, 14}; El error seria que no se declare de cuantos elementos constara el arreglo.

Error en Arrays bidimensionales


Cuando se declara un array de arrays (mejor conocido como array bidimensional o matriz), por ejemplo: Cdigo: int tabla[4][3]; Los elementos de este tipo de array pueden inicializarse de dos formas ligeramente distintas (y funcionales) utilizando listas de valores.

La primera consiste en utilizar una sola lista de valores, siguiendo nuestro ejemplo: Cdigo: int tabla[4][3] = {1, 2, 3, 11, 12, 13, 21, 22, 23};

y de esta manera se evitan muchos errores o bien se puede hacer de la siguiente manera en donde la lista de valores se utiliza para inicializar todos los elementos de la primera fila, despus la segunda fila, despus la tercera fila y as sucesivamente. Cdigo: tabla[0][0] tiene el valor 1 tabla[0][1] tiene el valor 2 tabla[0][2] tiene el valor 3 ... tabla[2][2] tiene el valor 23 Otra forma de hacerlo para evitar errores seria: con una lista "doble": Cdigo: int tabla[4][3] = { { 1, 2}, {11, 12}, {21, 22}, {31, 32} }; En este caso los valores de la primera lista se utilizan para inicializar la primera fila, los valores de la segunda lista se utilizan para inicializar la segunda fila, y as sucesivamente. Un array de caracteres como este: Cdigo: char dummy[128];

Errores comunes: Error muy comun: Almacena en una variable de un tipo "x" cuando deberia ser de otro tipo distinto. Error mas lgico de "Arrays de cadenas" es que falta incluir el archivo de inclusion o header <stdlib.h>. Cuando se realizan llamadas a la funcion scanf no se debe utilizar el operador "direccion de" (el '&') ya que al ser arrays los mismos campos generan el puntero de forma automatica.

Error # 1: No liberar memoria asignada por SafeArrayGetElement() cuando utiliza variantes Cuando utiliza SafeArrayGetElement(), asegrese de liberar la memoria que se ha asignado a la copia del elemento de matriz segura. Es el trabajo del llamador al asignar memoria copiando esta funcin el elemento de datos safearray y por lo tanto, tambin es el trabajo del llamador que libera esta memoria cuando esta memoria finaliza con ello. SafeArrayGetElement() asignar la memoria para los datos en el Variant (tal con respecto a un BSTR) y es el trabajo del llamador que libera todas las memorias asociadas a la variante. El enfoque mejor para ello es utilizar que funciona VariantClear(). Es un ejemplo: ... VARIANT varMyVal; // Variant allocated on stack HRESULT hResult; long ix; VariantInit(&varMyVal); ix = 1; // If the element in the safe array fetched was a BSTR, then the // appropriate memory will be allocated

for it, on the heap hResult = SafeArrayGetElement(m_psa, &ix, &varMyVal); // This will free the memory for the data element retrieved from // the Safe Array (say a BSTR) VariantClear(&varMyVal); Error # 2: No llamar a Release en punteros de interfaz COM. cuando utiliza QueryInterface() Si est utilizando componentes COM en proceso, asegrese de que libera todos los punteros de interfaz. Si no hace esto, puede dejar instancias de componentes COM no utilizados asignados en el espacio de memoria del proceso. El cdigo siguiente muestra el control adecuado de un puntero, pObj, obtenido va QueryInterface() en un objeto existente seleccionado por punk. El pObj- > <B> Release(); </B> disminuirn el recuento de referencia en el objeto pero no se liberar el objeto en momento de memoria an al contener punk una referencia a ello. Cuando > pUnk- <B> se llama a Release(); </B>, el recuento ref ir a 0 y se liberar el objeto. > > Release(), </B> entonces el pUnk- <B> Release(); </B> no liberarn el objeto y tendr una prdida de memoria en su proceso si omite el pObj- <B>. ... CMyAtlObj* pObj; if (!SUCCEEDED(pUnk->QueryInterface(CLSID_MyAtlObj, (void **)&pObj))) return NULL; //Use pObj ... pObj->Release(); // Needed because we called QueryInterface. ...

Para componentes COM que se registran para ejecutarse con Microsoft Transaction Server, ser escrita una entrada por Microsoft Transaction Server en el registro de sucesos de aplicacin de Windows NT cuando detecta que no se ha liberado correctamente un componente alojado antes de apagar. La entrada del registro de eventos tendr suceso de 4098 y una descripcin de "Count de Referencia de Objeto Inesperado". Si tiene estas entradas en el Registro de sucesos de NT y si est experimentando, se pierde memoria en aquellos paquetes MTS (procesos) entonces no es probable que se liberen correctamente punteros de interfaz COM.

Errores de codificacin

Errores de sintaxis: son errores en el programa fuente. Pueden deberse a palabras reservadas mal escritas, expresiones errneas o incompletas, variables que no existen, etc. Los errores de sintaxis se detectan en la fase de compilacin. El compilador, adems de generar el cdigo objeto, nos dar una lista de errores de sintaxis. De hecho nos dar slo una cosa o la otra, ya que si hay errores no es posible generar un cdigo objeto. Avisos: adems de errores, el compilador puede dar tambin avisos (warnings). Los avisos son errores, pero no lo suficientemente graves como para impedir la generacin del cdigo objeto. No obstante, es importante corregir estos avisos, ya que el compilador tiene que decidir entre varias opciones, y sus decisiones no tienen por qu coincidir con lo que nosotros pretendemos, se basan en las directivas que los creadores del compilador decidieron durante su creacin. Errores de enlazado: el programa enlazador tambin puede encontrar errores. Normalmente se refieren a funciones que no estn definidas en ninguno de los ficheros objetos ni en las libreras. Puede que hayamos olvidado incluir alguna librera, o algn fichero objeto, o puede que hayamos olvidado definir alguna funcin o variable, o lo hayamos hecho mal. Errores de ejecucin: incluso despus de obtener un fichero ejecutable, es posible que se produzcan errores. En el caso de los errores de ejecucin normalmente no obtendremos mensajes de error, sino que simplemente el programa terminar bruscamente. Estos errores son ms difciles de detectar y corregir. Existen programas auxiliares para buscar estos errores, son los llamados depuradores (debuggers). Estos programas permiten detener la ejecucin de nuestros programas, inspeccionar variables y ejecutar nuestro programa paso a paso. Esto resulta til para detectar excepciones, errores sutiles, y fallos que se presentan dependiendo de circunstancias distintas. Errores de diseo: finalmente los errores ms difciles de corregir y prevenir. Si nos hemos equivocado al disear nuestro algoritmo, no habr ningn programa que nos pueda ayudar a corregir los nuestros. Contra estos errores slo cabe practicar y pensar.
Nota: los compiladores clasifican los errores en dos tipos, dependiendo de lo serios que sean:

"Errores": son errores que impiden que el programa pueda ejecutarse, los programas con "errores" no pueden pasar de la fase de compilacin a la de enlazado, que es la fase en que se obtiene el programa ejecutable. "Warnings": son errores de poca entidad, (segn el compilador que, por supuesto, no tiene ni idea de lo que intentamos hacer). Estos errores no impiden pasar a la fase de enlazado, y por lo tanto es posible ejecutarlos. Debes tener cuidado si tu compilador de da una lista de "warnings", eso significa que has cometido algn error, en cualquier caso repasa esta lista e intenta corregir los "warnings".
A menudo recibiremos errores del compilador cuando usemos constantes long long sin aadir el sufijo LL, por ejemplo: if(x == 16575476522787) cout << "Nmero long long" << endl; Esta sentencia har que el compilador emita un error ya que no puede usar un tamao mayor sin una indicacin explcita.

Las excepciones son en realidad errores durante la ejecucin. Si uno de esos errores se produce y no implementamos el manejo de excepciones, el programa sencillamente terminar abruptamente. Es muy probable que si hay ficheros

abiertos no se guarde el contenido de los buffers, ni se cierren, adems ciertos objetos no sern destruidos, y se producirn fugas de memoria. En programas pequeos podemos prever las situaciones en que se pueden producir excepciones y evitarlos. Las excepciones ms habituales son las de peticiones de memoria fallidas. Veamos este ejemplo, en el que intentamos crear un array de cien millones de enteros:

#include <iostream> using namespace std; int main() { int *x = NULL; int y = 100000000; x = new int[y]; x[10] = 0; cout << "Puntero: " << (void *) x << endl; delete[] x; cin.get(); return 0; } El sistema operativo se quejar, y el programa terminar en el momento que intentamos asignar un valor a un elemento del array. Podemos intentar evitar este error, comprobando el valor del puntero despus del "new": #include <iostream> using namespace std; int main() { int *x = 0; int y = 100000000; x = new int[y]; if(x) { x[10] = 0; cout << "Puntero: " << (void *) x << endl; delete[] x; } else { cout << "Memoria insuficiente." << endl; } cin.get(); return 0; } Pero esto tampoco funcionar, ya que es al procesar la sentencia que contiene el operador "new" cuando se produce la excepcin. Slo nos queda evitar peticiones de memoria que puedan fallar, pero eso no es previsible. Sin embargo, C++ proporciona un mecanismo ms potente para detectar errores de ejecucin. Las excepciones. Para ello disponemos de tres palabras reservadas extra: try, catch y throw, veamos un ejemplo: #include <iostream> using namespace std; int main() { int *x; int y = 100000000; try {

x = new int[y]; x[0] = 10; cout << "Puntero: " << (void *) x << endl; delete[] x; } catch(std::bad_alloc&) { cout << "Memoria insuficiente" << endl; } cin.get(); return 0; } La manipulacin de excepciones consiste en transferir la ejecucin del programa desde el punto donde se produce la excepcin a un manipulador que coincida con el motivo de la excepcin. Como vemos en este ejemplo, un manipulador consiste en un bloque "try", donde se incluye el cdigo que puede producir la excepcin. A continuacin encontraremos uno o varios manipuladores asociados al bloque "try", cada uno de esos manipuladores empiezan con la palabra "catch", y entre parntesis una referencia o un objeto. En nuestro ejemplo se trata de una referencia a un objeto bad_alloc, que es el asociado a excepciones consecuencia de aplicar el operador "new". Tambin debe existir una expresin "throw", dentro del bloque "try". En nuestro caso es implcita, ya que se trata de una excepcin estndar, pero podra haber un "throw" explcito, por ejemplo: #include <iostream> using namespace std; int main() { try { throw 'x'; // valor de tipo char } catch(char c) { cout << "El valor de c es: " << c << endl; } catch(int n) { cout << "El valor de n es: " << n << endl; } cin.get(); return 0; } El "throw" se comporta como un "return". Lo que sucede es lo siguiente: el valor devuelto por el "throw" se asigna al objeto del "catch" adecuado. En este ejemplo, al tratarse de un carcter, se asigna a la variable 'c', en el "catch" que contiene un parmetro de tipo "char". En el caso del operador "new", si se produce una excepcin, se hace un "throw" de un objeto de la clase "std::bad_alloc", y como no estamos interesados en ese objeto, slo usamos el tipo, sin nombre. El manipulador puede ser invocado por un "throw" que se encuentre dentro del bloque "try" asociado, o en una de las funciones llamadas desde l. Cuando se produce una excepcin se busca un manipulador apropiado en el rango del "try" actual. Si no se encuentra se retrocede al anterior, de modo recursivo, hasta encontrarlo. Cuando se encuentra se destruyen todos los objetos locales en el nivel donde se ha localizado el manipulador, y en todos los niveles por los que hemos pasado. #include <iostream> using namespace std; int main() { try { try {

try { throw 'x'; // valor de tipo char } catch(int i) {} catch(float k) {} } catch(unsigned int x) {} } catch(char c) { cout << "El valor de c es: " << c << endl; } cin.get(); return 0; } En este ejemplo podemos comprobar que a pesar de haber hecho el "throw" en el tercer nivel del "try", el "catch" que lo procesa es el del primer nivel. Los tipos de la expresin del "throw" y el especificado en el "catch" deben coincidir, o bien, el tipo del catch debe ser una clase base de la expresin del "throw". La concordancia de tipos es muy estricta, por ejemplo, no se considera como el mismo tipo "int" que "unsigned int". Si no se encontrase ningn "catch" adecuado, se abandona el programa, del mismo modo que si se produce una excepcin y no hemos hecho ningn tipo de manipulacin de excepciones. Los objetos locales no se destruyen, etc. Para evitar eso existe un "catch" general, que captura cualquier "throw" para el que no exista un "catch": #include <iostream> using namespace std; int main() { try { throw 'x'; // } catch(int c) { cout << "El valor de c es: " << c << endl; } catch(...) { cout << "Excepcin imprevista" << endl; } cin.get(); return 0; }

Vous aimerez peut-être aussi