mikrocontroller.net

Forum: PC-Programmierung Segmentation fault bei Linux


Autor: Erik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo allerseits,

warum liefert der folgende code einen "segmentation fault error", er 
wird unter linux Suse 10.1 compiliert und ausgeführt.

#include <mysql/mysql.h>
#include <stdio.h>
#include <string.h>

int main()
{
   MYSQL mysql;
   MYSQL_RES *res;
   MYSQL_ROW row;

   char query[80];
   mysql_init(&mysql);
   mysql_real_connect(&mysql,"localhost","yyy","xxx","test",0,NULL,0);
   sprintf(query,"SELECT * FROM test");
   mysql_real_query(&mysql,query,(unsigned int)strlen(query));
   res = mysql_use_result(&mysql);
   while(row = mysql_fetch_row(res))
    printf("%s %sn",row[0],row[1]);
   mysql_free_result(res);
   return 0;
}


Was muss geändert werden ?
Danke im Voraus !

Autor: Ulrich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
als erstes würde ich mal versuchen rauszufinden an welche rStelle der 
Fehlerpassiert. Schonmal den gdb angeworfen?

Autor: Μαtthias W. (matthias) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

oder erstmal anfangen auch nur ein Mindestmaß an Fehlerbehandlung 
einzubauen. Wer sagt denn das mysql_init(&mysql) ff. überhaupt 
erfolgreich sind.

Matthias

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gdb deinprogramm
(gdb) run
[Fehlermeldung]
(gdb) backtrace

Autor: Niquo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also
   MYSQL mysql;
   mysql_init(&mysql);
sieht schon mal ganz böse aus, weil mysql_init doch den Speicher 
allozieren will. Demnach würde ich mal das hier versuchen:
   MYSQL *mysql = (MYSQL*) 0;
   mysql_init(mysql);

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Unabhängig vom konkreten Problem zum Stil: Stichwort "Defensive 
Programmierung". Geh davon aus, dass Funktionen, die Fehler 
zurückliefern können, es auch ab und zu tun werden.

Autor: Erik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke erstmal, seitens der DB müsste es klappen, der obige code ist 
nicht der einzige den ich probiert habe.

MYSQL *mysql = (MYSQL*) 0; ändert leider nichts.


etwas länger und "sicherer" und ebenfalls segfault:

#include <mysql/mysql.h>
#include <stdio.h>
#include <string.h>

int main(){
   MYSQL *mysql;
   MYSQL_RES *res;
   MYSQL_ROW row;
   char *query;
   int t,r;

   mysql_init(mysql);
   if (!mysql_real_connect(mysql,"localhost","apc0", 
"xxx","test",0,NULL,0))
   {
       printf( "Error connectin ot database: %s\n",mysql_error(mysql));
   }
   else printf("Connected...\n");

   query="select * from test";

   t=mysql_real_query(mysql,query,(unsigned int) strlen(query));
   if (t)
   {
      printf("Error making query: %s\n",
              mysql_error(mysql));
   }
   else printf("Query made...\n");
   res=mysql_use_result(mysql);
   for(r=0;r<=mysql_field_count(mysql);r++){
           row=mysql_fetch_row(res);
           if(row<0) break;
           for(t=0;t<mysql_num_fields(res);t++){
                   printf("%s ",row[t]);
           }
           printf("\n");
   }
   mysql_close(mysql);
return 0;
}


gdb liefert hierzu

Program received signal SIGSEGV, Segmentation fault.
0xb7d200e7 in memset () from /lib/libc.so.6
(gdb) backtrace
#0  0xb7d200e7 in memset () from /lib/libc.so.6
#1  0xb7e0e70a in mysql_init () from /usr/lib/libmysqlclient.so.15
#2  0x08048742 in main ()


Hmm, und was sagt uns das ?

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dass memset(), welches von mysql_init() aufgerufen wurde, welches 
wiederum von main() aufgerufen wurde, auf einen ungültigen 
Speicherbereich zugreift. Der Grund ist, dass du für mysql keinen 
Speicher reserviert hast, mysql_init aber davon ausgeht dass es sich um 
einen gültigen Zeiger handelt. Die Lösung hat dir Niquo schon verraten, 
und sie steht auch in der Dokumentation zu mysql_init(): "If mysql is a 
NULL pointer, the function allocates, initializes, and returns a new 
object." Du musst den Zeiger also mit 0 (bzw. dem Makro NULL, zur 
besseren optischen Unterscheidung zwischen Integern und Zeigern) 
initialisieren:
MYSQL *mysql = NULL;

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da war die erste Version besser. Die zweite verwendet einen 
undefinierter Pointer (=> crash in memset). Entweder Platz übergeben 
(1.Version) oder NULL (Niquo).

Autor: Erik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Hilfe, sowie ich

MYSQL *mysql = 0;

verwende erhalte ich folgendes:

Program received signal SIGSEGV, Segmentation fault.
0xb7dd5c54 in mysql_real_connect () from /usr/lib/libmysqlclient.so.15
(gdb) backtrace
#0  0xb7dd5c54 in mysql_real_connect () from 
/usr/lib/libmysqlclient.so.15
#1  0x0804878c in main ()
(gdb)


Was ich nicht verstehe ist, dass dies alles Beispiel-codes von MySQL 
Seiten sind, die können doch nicht völlig "daneben" sein ?!?

Autor: Erik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe A.Ks post erst jetzt gelesen - und bin nun endgültig verwirrt, was 
passt denn nun ?

Autor: FBI (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lies Dir die Docs von MySQL durch!

Es gehen beide Varianten von mysql_init.
Aber nur wenn man sie auch richtig benutzt!!!
Also enweder:
MYSQL mysql;
mysql_init(&mysql);
oder:
MYSQL *pmysql;
pmysql = mysql_init(NULL);
if(!pmysql) {
  // ERROR
}
bzw.
MYSQL *pmysql = NULL;
pmysql = mysql_init(pmysql);
if(!pmysql) {
  // ERROR
}

CU Frank

Autor: Erik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, vielen Dank, hab´s endlich zum Laufen gebracht, war nach dem MYSQL 
°pmysql=NULL Problem noch ein anderer segfault Fehler im obigen code.

Vielen Dank an alle !

Autor: FBI (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>anderer segfault ...

Ja vermutlich beim printf :-)
Besser wär wohl gewesen:
printf("%s ", row[t] ? row[t] : "<NULL>");
Steht aber auch so direkt als Beispiel in der Docu zu mysql_fetch_row.

CU

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.