Símbolos no encontrados para arquitectura x86/x64

Iniciado por digimikeh, 23 Abril 2019, 19:28 PM

0 Miembros y 1 Visitante están viendo este tema.

digimikeh

Hola!

Estoy trabajando con QT Creator y tengo el siguiente código:

Código (cpp) [Seleccionar]

    struct Constants{

        static const char * DB_FILE_NAME;
        static const char * DB_FULL_PATH;
        static const char * DB_FULL_PATH_NAME;

        Constants();
        ~Constants();

    };

    Constants::Constants(){
        DB_FILE_NAME = "data.db";
        DB_FULL_PATH = "./";
        DB_FULL_PATH_NAME = "./data.db";
    }

    Constants::~Constants(){
        delete DB_FILE_NAME;
        delete DB_FULL_PATH;
        delete DB_FULL_PATH_NAME;
    }




Sin embargo, al compilar, me dice :


symbol(s) not found for architecture x86_64
linker command failed with exit code 1 (use -v to see invocation)


Definí los valores de las constantes estéticas fuera del structs debido a que tenia entendido que nunca se hacen en la misma declaración... a que puede deberse este error?

gracias.
Dungeons & dragons;
dragons.Attack();

K-YreX

No sé exactamente a qué se debe ese error, por lo que he leído puede ser un problema debido a que estés trabajando con varios ficheros y tengas un error en la orden de compilación.

Lo que sí puedo decirte es que estás guardando una cadena de <char> en unos punteros a <char> sin reservar memoria y después estás liberando esa memoria (memoria que no has reservado)... Espero que te sirva de ayuda.

Suerte :-X
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

digimikeh

Tienes razón, se me había pasado eso de solicitar memoria ...  gracias..

El error lo he visto mas en OSX..
Dungeons & dragons;
dragons.Attack();

digimikeh

#3
Código (cpp) [Seleccionar]


struct Constants{

       static const char * DB_FILE_NAME;
       static const char * DB_FULL_PATH;
       static const char * DB_FULL_PATH_NAME;

       ~Constants();

   };

   //Aqui esta lo nuevo:
   const char * Constants::DB_FILE_NAME = "data.db";
   const char * Constants::DB_FULL_PATH = "./";
   const char * Constants::DB_FULL_PATH_NAME = "./data.db";

   Constants::~Constants(){
       delete DB_FILE_NAME;
       delete DB_FULL_PATH;
       delete DB_FULL_PATH_NAME;
   }



Ya vi, mi error era que estaba inicializando mal, cuando los miembros son static, debo hacerlo de la forma en las lineas 13, 14 y 15.  Parece ser que la definición de los miembros estáticos es levemente diferente a la de un miembro común y corriente, porque he necesitado colocar las palabras "const char *" nuevamente, como si las estuviera declarando.

Lo otro que me di cuenta es que no he necesitado solicitar memoria dinámica (no he probado aun, puede que mi aplicación se cierre), lo cual me parece extraño, tenia entendido que todos los punteros deben solicitar memoria dinámica..  C++ es como una nena.  ;D
Dungeons & dragons;
dragons.Attack();

CalgaryCorpus

Aqui mi perfil en LinkedIn, invitame un cafe aqui

digimikeh

Si cierto, otro error de mi parte, ya he quitado los deletes...

al final también quité el struct... las variables estáticas quedaron directamente fuera.. dentro de un namespace



namespace UTools{

     static const char * DB_FILE_NAME = "data.db";
     static const char * DB_FULL_PATH = "./";
     static const char * DB_FULL_PATH_NAME = "./data.db";

}



Y al parecer, char * es una excepción a la regla, es lo único que implícitamente solicita memoria dinámica, sin que yo escriba new... acabo de hacer las pruebas....

Dungeons & dragons;
dragons.Attack();

Loretz

#6
CitarY al parecer, char * es una excepción a la regla, es lo único que implícitamente solicita memoria dinámica ...

No, no se trata de una excepción, lo que sucede es que las expresiones como "data.db" son de tipo "string literal", que tienen"static storage duration" [https://en.cppreference.com/w/c/language/static_storage_duration], por lo que existen durante toda la vida del programa y se inicializan antes de main().

Por ejemplo, el tipo de "data.db" es const char[8] (los 7 caracteres visibles más el 0 del final). Como los arrays decaen en punteros, es también natural escribir:
const char* file_name = "data.db";
Entonces, file_name es un puntero a carácter que apunta a la primera 'd' del array, se le asigna esa dirección de memoria, que ya existe, por eso es que no es necesario crearla.

Otra cosa; al declarar las variables "static", si vas a poner tu UTools en un .h, estarás haciendo que cada unidad donde se incluya (cada .cpp) tenga su propia copia de todas esas variables. En este caso son todas const char* y nadie las va a modificar, pero de todos modos creo que conviene tenerlo en cuenta.


RayR

#7
Sí, los punteros char son una excepción, pero no exactamente como piensas. Por comodidad se pueden inicializar de esa forma, pero en ningún momento se está reservando memoria dinámica.

Cuando declaras e inicializas punteros char así:

char *ptr = "hola mundo";

El compilador crea la cadena "hola mundo", y en tiempo de compilación (no dinámicamente) la almacena en un lugar de la memoria, y hace que ptr apunte a esa dirección. Y a diferencia de una cadena reservada dinámicamente, en este caso no se deben modificar sus datos. El estándar dice que intentar algo como esto: (que con cadenas reservadas dinámicamente funcionaría sin problemas)

ptr[0] = 'H';

resulta en comportamiento indefinido, es decir, el resultado es impredecible, y por eso no se debe hacer. Normalmente, se producirá un error de violación de acceso, y se cerrará tu programa. Esto se debe a que, por cuestiones de rendimiento, los compiladores suelen almacenar las cadenas literales en memoria de sólo lectura (por ejemplo, en el segmento de código/texto junto con elas instrucciones ejecutables de tu programa).

En tu caso, no tendrás problemas, ya que los estás declarando como punteros a char constante, por lo que el compilador te marcaría error si intentaras modificar sus datos, pero es importante conocer la diferencia. Si necesitas punteros dinámicos, sean o no char, no queda de otra que reservar manualmente su memoria.

Editado: Por cierto, en relación a tu error, ayudaría si pusieras el mensaje completo (el linker debería decirte cuáles símbolos no encuentra), pero seguramente se debe a que te está faltando enlazar con alguna biblioteca que estás usando.

digimikeh

Gracias por las aclaraciones...

Estoy más claro ahora

Saludos  :D
Dungeons & dragons;
dragons.Attack();