tutorials.de Buch-Aktion 05/2012
ERLEDIGT
JA
ANTWORTEN
4
ZUGRIFFE
739
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    llf Tutorials.de Gastzugang
    Hallo, nach dem ich heute endlich C++ mit MySQL zum Laufen brachte, kam mir eine Idee. Da ich ein Spiel programmiere (in SDL), will ich dies zu einem Onlinegame umbauen. Dafür will ich die MySQL-Datenbank als Login-Server verwenden. Was bedeutet, der Nutzer gibt Seine Email-Adresse und sein Passwort ein und das Skript überprüft dann den Rest. Als erstes wollte ich mit der MySQL-Funktion beginnen. Damit aber alles Ordentlich bleibt will ich SDL und MySQL klar von einander trennen. Jetzt habe ich eine Anwendung geschrieben, zum Testen ob das mit einer zweiten .cpp Datei und einer Header überhaupt geht. Compilen lässt es sich auch aber ausführen nicht. Wenn ich versuche es auszuführen, dann kommt folgende Fehler Meldung: Speicherzugriffsfehler. Ich hab' mir ein Build-Skript geschrieben (Shell). Wenn ich das ausführe kommt Segmentation fault. Was kann ich machen?

    Hier der Quelltext von allen Dateien:

    mysql.cpp
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    
    #include <mysql/mysql.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include "mysql.h"
     
    THE_MYSQL::THE_MYSQL()
    {
        conn = mysql_init(NULL);
    }
     
    THE_MYSQL::~THE_MYSQL()
    {
    }
     
    void THE_MYSQL::connect()
    {
        if(!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) {
            fprintf(stderr, "%s\n", mysql_error(conn));
            exit(1);
        }
    }
     
    void THE_MYSQL::disconnect()
    {
        mysql_free_result(res);
        mysql_close(conn);
    }
     
    MYSQL_RES *THE_MYSQL::send_query(char *query)
    {
        if(mysql_query(conn, query)) {
            fprintf(stderr, "%s\n", mysql_error(conn));
            exit(1);
        }
     
        return mysql_use_result(conn);
    }

    mysql.h
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    #ifndef MYSQL_H
    #define MYSQL_H
     
    #include <mysql/mysql.h>
     
    class THE_MYSQL
    {
    public:
        char *server;
        char *user;
        char *password;
        char *database;
     
        THE_MYSQL();
        ~THE_MYSQL();
        void connect();
        void disconnect();
        MYSQL_RES *send_query(char *query);
     
    private:
        MYSQL     *conn;
        MYSQL_RES *res;
    };
     
    #endif

    main.cpp
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    #include <mysql/mysql.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include "mysql.h"
     
    int main() {
        MYSQL_RES *resource;
        MYSQL_ROW  row;
     
        THE_MYSQL *connection;
        connection->server   = "localhost";
        connection->user     = "root";
        connection->password = "imkampe";
        connection->database = "game";
        connection->connect();
     
        resource = connection->send_query("show tables");
     
        connection->disconnect();
    }

    compile.sh
    Code :
    1
    2
    3
    4
    
    g++ -c main.cpp -o main.o
    g++ -c mysql.cpp -o mysql.o
    g++ -o output-file $(mysql_config --cflags) main.cpp mysql.cpp $(mysql_config --libs)
    ./output-file

    Danke für alle Antworten.

    PS: Bitte sagt jetzt nicht das es doch viel praktischer ist ein Makefile zu benutzen. Ich finde Makefiles zu umständlich und hab' oft schlechte Erfahrungen gesammelt mit ihnen.
     

  2. #2
    Avatar von sheel
    sheel sheel ist offline Moderator
    tutorials.de Moderator
    Registriert seit
    Jul 2007
    Beiträge
    4.501
    Hi

    Wie, das Buildskript (compile.sh) macht Segmentation Faults?
    Nicht eher der Aufruf des Programms am Schluss?

    Zum Fehler:
    Dieser Teil im main:
    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    THE_MYSQL *connection;
    connection->server   = "localhost";
    connection->user     = "root";
    connection->password = "imkampe";
    connection->database = "game";
    connection->connect();
     
    resource = connection->send_query("show tables");
     
    connection->disconnect();
    Da machst du mi connection einen Pointer.
    Dieser Pointer kann auf ein THE_MYSQL zeigen.
    Tut er aber nicht. Du lässt ihn leer und willst dann das THE_MYSQL drinnen, das es noch gar nicht gibt, verwenden.

    Entweder du vergisst den Pointer und legst einfach ein wirkliches Objekt an:
    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    THE_MYSQL connection;
    connection.server   = "localhost";
    connection.user     = "root";
    connection.password = "imkampe";
    connection.database = "game";
    connection.connect();
     
    resource = connection.send_query("show tables");
     
    connection.disconnect();
    (Stern beim Anlegen weg und statt -> immer . nehmen)

    oder du verwendest new und delete:
    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    THE_MYSQL *connection;
    connection = new THE_MYSQL(); //neu
    connection->server   = "localhost";
    connection->user     = "root";
    connection->password = "imkampe";
    connection->database = "game";
    connection->connect();
     
    resource = connection->send_query("show tables");
     
    connection->disconnect();
    delete connection; //neu

    Die Logindaten solltest du übrigens nicht im Klartext im Programm speichern.
    Das kann jeder auslesen.

    Gruß
     

  3. #3
    llf Tutorials.de Gastzugang
    Also das mit den Login-Daten will ich später noch mit MD5 verschlüsseln.
    Ich hab jetzt mal ein paar Änderungen vorgenommen.
    Ich hab jetzt folgendes Skript:

    mysql.cpp
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    
    #include <mysql/mysql.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include "mysql.h"
     
    THE_MYSQL::THE_MYSQL()
    {
        conn = mysql_init(NULL);
    }
     
    THE_MYSQL::~THE_MYSQL()
    {
    }
     
    void THE_MYSQL::connect()
    {
        if(!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) {
            fprintf(stderr, "%s\n", mysql_error(conn));
            exit(1);
        }
    }
     
    void THE_MYSQL::disconnect()
    {
        mysql_free_result(res);
        mysql_close(conn);
    }
     
    MYSQL_RES *THE_MYSQL::send_query(char *query)
    {
        if(mysql_query(conn, query)) {
            fprintf(stderr, "%s\n", mysql_error(conn));
            exit(1);
        }
     
        return mysql_use_result(conn);
    }

    mysql.h
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    #ifndef MYSQL_H
    #define MYSQL_H
     
    #include <mysql/mysql.h>
    #include <string>
     
    class THE_MYSQL
    {
    public:
        char *server;
        char *user;
        char *password;
        char *database;
     
        THE_MYSQL();
        ~THE_MYSQL();
        void connect();
        void disconnect();
        MYSQL_RES *send_query(char *query);
     
    private:
        MYSQL     *conn;
        MYSQL_RES *res;
    };
     
    #endif

    main.cpp
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    #include <mysql/mysql.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include "mysql.h"
     
    int main() {
        MYSQL_RES *resource;
        MYSQL_ROW  row;
     
        THE_MYSQL connection;
        connection.server   = "localhost";
        connection.user     = "root";
        connection.password = "imkampe";
        connection.database = "game";
        connection.connect();
     
        resource = connection.send_query("show tables");
     
        connection.disconnect();
        return 0;
    }

    Das mit dem Speicherzugriffsfehler / Segmentation fault ist jetzt beim Compilen weg. Jetzt kommt allerdings folgendes: Bus error / Bus Speicherzugriffsfehler.
    Ich hab es jetzt debugt und fest gestellt, dass der Bus error daran liegt:
    Code :
    1
    
    mysql_free_result(res);

    Wenn ich das weg lasse, dann funktioniert es. Aber ich finde dass das eine nicht so tolle Methode ist, weil das Skript dann nicht sauber beendet wird.

    Gibt's da vielleicht eine Lösung?

    MFG llf

    PS:
    Ich hab auch mein compile-Skript umgebaut, das keine Warnungen mehr erscheinen.
    compile.sh
    Code :
    1
    2
    3
    4
    
    g++ -c main.cpp -o main.o -Wno-write-strings
    g++ -c mysql.cpp -o mysql.o
    g++ -o output-file $(mysql_config --cflags) main.cpp mysql.cpp $(mysql_config --libs) -Wno-write-strings
    ./output-file
     

  4. #4
    llf Tutorials.de Gastzugang
    Okay,
    ich hab mal wieder den Wald vor lauter Bäumen nicht gesehen.
    Noch schöne Woche
     

  5. #5
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Hi.
    Zitat Zitat von llf Beitrag anzeigen
    Ich hab auch mein compile-Skript umgebaut, das keine Warnungen mehr erscheinen.
    Warnungen sind in der Regel aber sehr nützlich. Sie weisen meistens auf einen Fehler hin.

    Die Warnungen einfach zu unterdrücken ist keine gute Idee. Versuche die Warnungen zu verstehen und ändere die Fehler im Code ab die zu den Warnungen führen.

    Stringliterale sind nunmal konstant und es führt letztendlich zu einem Absturz wenn man versucht diese zu ändern.

    Du müßtest einfach nur "const char*" statt "char*" verwenden:
    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    class THE_MYSQL
    {
    public:
        const char *server;
        const char *user;
        const char *password;
        const char *database;
     ...
    };
    Wobei Attribute einer Klasse nie public sein sollten. OOP, data hiding. Warum übergibst du die Werte nicht im Konstruktor? So wie es jetzt ist, kann man einfach eine THE_MYSQL Instanz erzeugen die unbenutzbar ist, da sie nicht vollständig initialisiert ist.

    Gruß
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

Ähnliche Themen

  1. Segmentation fault
    Von Vippis im Forum C/C++
    Antworten: 21
    Letzter Beitrag: 05.12.10, 22:56
  2. Segmentation Fault
    Von Schnoogle im Forum C/C++
    Antworten: 1
    Letzter Beitrag: 10.02.10, 12:25
  3. Segmentation Fault
    Von flogy92 im Forum C/C++
    Antworten: 23
    Letzter Beitrag: 28.01.09, 09:31
  4. Segmentation fault
    Von stain im Forum Linux & Unix
    Antworten: 0
    Letzter Beitrag: 28.04.08, 18:34
  5. C: Segmentation fault
    Von Westbär im Forum C/C++
    Antworten: 3
    Letzter Beitrag: 05.07.07, 10:46

Stichworte