Publicado el 23 de Febrero del 2019
1.034 visualizaciones desde el 23 de Febrero del 2019
127,0 KB
35 paginas
Creado hace 22a (16/05/2003)
Errores más comunes en C++
Sergio Luján Mora
16 de mayo de 2003
1.
Introducción
En este documento se han recogido los errores más habituales que comete una persona cuando co-
mienza a programar con el lenguaje de programación C++. Los errores se han clasicado en las siguientes
categorías:
Sobre el chero makele y la compilación.
Sobre las directivas de inclusión.
Sobre las clases.
Sobre la sobrecarga de los operadores.
Sobre la memoria.
Sobre las cadenas.
Varios.
Los mensajes de error pueden cambiar de una versión de compilador a otro. Por ejemplo, el siguiente
código contiene dos errores, porque se confunde el manejo de objetos y punteros a objetos:
UnaClase a, *b;
b = &a;
cout << a->propiedad;
cout << b.propiedad;
Si se compila con el compilador g++ 2.95.4 de GNU se obtiene el siguiente mensaje de error:
prueba.cc: In function `int main(...)':
prueba.cc:12: base operand of `->' has non-pointer type `UnaClase'
prueba.cc:13: request for member `propiedad' in `b', which is of non-aggregate
type `UnaClase *'
Si se compila con el compilador bcc32 5.5.1 de Borland se obtiene el siguiente mensaje de error:
Error E2288 prueba.cc 12: Pointer to structure required on left side of -> or ->*
in function main()
Error E2294 prueba.cc 13: Structure required on left side of . or .* in function
main()
1
Como se ha comentado previamente, el formato de los mensajes de error cambia de un compilador a
otro, aunque suelen tener un estructura similar. En general, cada mensaje de error consta de:
El nombre del archivo donde se ha detectado el error.
El número de línea dentro del archivo donde se ha detectado el error.
Un número de referencia de un tipo de error.
Una breve descripción del error.
Por otro lado, el mensaje de error también puede cambiar si previamente han aparecido otros errores
durante el proceso de compilación (pueden aparecer errores donde realmente no hay errores o pueden
desaparecer errores verdaderos). Por ejemplo, el siguiente código:
...
UnaClase&
UnaClase::operator=(Unaclase& a)
{
...
}
...
produce los siguientes mensajes de error, de los cuales sólo el primero es válido (el resto son falsos errores
inducidos por el primer error):
unaclase.cc:43: `Unaclase' was not declared in this scope
unaclase.cc:43: `a' was not declared in this scope
unaclase.cc:44: declaration of `operator =' as non-function
unaclase.cc:44: invalid declarator
unaclase.cc:44: syntax error before `{'
unaclase.cc:46: ANSI C++ forbids declaration `dim' with no type
unaclase.cc:46: `a' was not declared in this scope
unaclase.cc:47: ANSI C++ forbids declaration `v' with no type
unaclase.cc:47: invalid use of member `UnaClase::dim'
unaclase.cc:48: parse error before `for'
unaclase.cc:48: invalid use of member `UnaClase::dim'
unaclase.cc:48: parse error before `;'
unaclase.cc:48: syntax error before `++'
El error se produce porque Unaclase no está denido: cambiando Unaclase por UnaClase se resuelve
el problema y desaparecen todos los mensajes de error. Conclusión: los errores hay que resolverlos desde
el principio hasta el nal del código, ya que al resolver un error pueden desaparecer mensajes de error
falsos.
Los mensajes de error que se recogen en este documento han sido generados por el compilador g++
de GNU versión 2.95.4. Se ha intentado buscar ejemplos sencillos para mostrar la esencia del problema.
Debido a ello, en algunos casos pueden parecer estúpidos los ejemplos.
Los errores más difíciles de detectar son los relacionados con el manejo de memoria. En especial los
de violación de segmento (Segmentation fault), ya que no siempre se produce el mensaje de error (lo
que no signica que no exista un error). Como la memoria se reserva por trozos (por ejemplo, de 16
en 16 bytes), una operación incorrecta que invada una zona de memoria no válida puede pasar siempre
inadvertida. Otras veces, el mensaje de error se produce después del punto donde existe el error (el error
se maniesta en un punto donde realmente no existe). Para resolver este tipo de errores, lo mejor es
emplear un depurador y realizar una traza del código desde el principio.
2
2. Sobre el chero makele y la compilación
Compilar código en C++ con el compilador de C (gcc). Ejemplo:
gcc -c unaclase.cc
gcc -c prueba.cc
gcc -o prueba prueba.o unaclase.o
Mensaje de error: En el proceso de compilación no se genera un mensaje de error. En el proceso de
enlazado (última ejecución de gcc) se genera un mensaje de error porque no se enlazan las librerías
con el código de C++.
prueba.o: In function `main':
prueba.o(.text+0x28): undefined reference to `endl(ostream &)'
prueba.o(.text+0x35): undefined reference to `cout'
prueba.o(.text+0x3a): undefined reference to `ostream::operator<<(char const *)'
Solución: Emplear el compilador de C++ (g++).
g++ -c unaclase.cc
g++ -c prueba.cc
g++ -o prueba prueba.o unaclase.o
Poner espacios en blanco en vez de emplear tabulador en el chero makefile. Ejemplo: El subrayado
(_) representa un espacio en blanco.
prueba: prueba.o unaclase.o
________g++ -o prueba prueba.o unaclase.o
Mensaje de error:
makefile:2: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.
Solución: Emplear el tabulador en vez de espacios en blanco.
prueba: prueba.o unaclase.o
g++ -o prueba prueba.o unaclase.o
No existe un chero de una regla de dependencia (por ejemplo, porque se ha escrito mal el nombre
del chero). Ejemplo:
prueba.o: prueba.cc UnaClase.h
g++ -c prueba.cc
Mensaje de error:
make: *** No rule to make target `UnaClase.h', needed by `prueba.o'. Stop.
3
Solución: Vericar que los nombres de los cheros están bien escritos y que los cheros existen.
prueba.o: prueba.cc unaclase.h
g++ -c prueba.cc
Compilar un chero cuyo nombre una vez compilado no coincide con el esperado. Ejemplo: El
compilador genera el chero pruebaa.o, pero lo que se quiere obtener es el chero prueba.o.
prueba: prueba.o unaclase.o
g++ -o prueba prueba.o unaclase.o
prueba.o: pruebaa.cc unaclase.h
g++ -c pruebaa.cc
Mensaje de error:
g++: prueba.o: No such file or directory
Solución: Vericar que los nombres de los cheros están bien escritos y que los cheros existen.
prueba.o: prueba.cc unaclase.h
g++ -c prueba.cc
Al enlazar, no incluir un chero necesario. Ejemplo:
g++ -c unaclase.cc
g++ -c prueba.cc
g++ -o prueba prueba.o
Mensaje de error:
prueba.o: In function `main':
prueba.o(.text+0xe): undefined reference to `UnaClase::UnaClase(void)'
prueba.o(.text+0x2f): undefined reference to `UnaClase::~UnaClase(void)'
prueba.o(.text+0x4a): undefined reference to `UnaClase::~UnaClase(void)'
Solución: Vericar que en el proceso de enlazado se tienen en cuenta todos los cheros necesarios.
g++ -c unaclase.cc
g++ -c prueba.cc
g++ -o prueba prueba.o unaclase.o
4
3. Sobre las directivas de inclusión
Los espacios en blanco son signicativos dentro de los < > o los " " de una directiva de inclusión.
Ejemplo:
#include < iostream >
Mensaje de error:
unaclase.cc:1:
iostream : No such file or directory
Solución: Eliminar los espacios en blanco.
#include <iostream>
Emplear < > en vez de " " para un archivo de cabecera que no es estándar. Ejemplo:
#include <unaclase>
// O también
#include <unaclase.h>
Mensaje de error:
unaclase.cc:3: unaclase: No such file or directory
// O también
unaclase.cc:3: unaclase.h: No such file or directory
Solución: Emplear " " y poner siempre el nombre completo del chero de cabecera. Sólo para las
cabeceras de la biblioteca estándar se puede emplear indistintamente < > o " " y con o sin .h.
#include "unaclase.h"
Incluir múltiples veces el mismo chero de cabecera. Ejemplo:
#include "unaclase.h"
#include "unaclase.h"
Mensaje de error:
In file included from prueba.cc:3:
unaclase.h:5: redefinition of `class UnaClase'
unaclase.h:16: previous definition here
Solución: Emplear las guardas de inclusión, que evita el problema de la redenición cuando se incluye
el mismo chero de cabecera múltiples veces. Para evitar conictos de nombres en las guardas, es
conveniente elegir nombres largos y extraños. Todas las cabeceras estándar tienen guardas de
inclusión, así que no hay que preocuparse en incluirlas varias veces.
5
#ifndef __UNACLASE__
#define __UNACLASE__
class UnaClase
{
...
};
#endif
Emplear un punto (.) en el nombre de una guarda de inclusión. Ejemplo:
#ifndef __UNACLASE.H__
#define __UNACLASE.H__
Mensaje de error: No se produce un mensaje de error. Se trata de una advertencia: el identicador
denido se trunca hasta el carácter no válido.
unaclase.h:1: warning: garbage at end of `#ifndef' argument
unaclase.h:2: warning: missing white space after `#define __UNACLASE'
Solución: Emplear únicamente los mismos caracteres que se emplean en el nombre de una función
o de una variable.
#ifndef __UNACLASE__
#define __UNACLASE__
No separar el nombre de una guarda de inclusión de las instrucciones de compilación condicional.
Ejemplo:
#ifndef__UNACLASEH__
#define__UNACLASEH__
Mensaje de error:
In file included from unaclase.cc:3:
unaclase.h:31: unbalanced `#endif'
Solución: Separar con un espacio en blanco como el nombre de la guarda de inclusión de las ins-
trucciones de compilación condicional.
#ifndef __UNACLASE__
#define __UNACLASE__
6
4. Sobre las clases
Emplear el nombre de la clase y el operador de ámbito (::) incorrectamente al denir el código de
una función. Ejemplo:
UnaClase::UnaClase& operator=(UnaClase& a)
{
...
}
Mensaje de error:
unaclase.cc:14: `operator =(UnaClase &)' must be a nonstatic member function
Solución: Primero se tiene que poner el tipo del valor de retorno de la función y a continuación el
nombre de la clase y el operador de ámbito.
UnaClase& UnaClase::operator=(UnaClase& a)
{
...
}
No colocar el modicador de visibilidad public: antes de la declaración de los constructores, el
destructor y otras funciones miembro. Ejemplo:
class UnaClase
{
UnaClase();
~UnaClase();
...
};
Mensaje de error: No se produce un mensaje
Comentarios de: Errores más comunes en C++ (0)
No hay comentarios