Forum: PC-Programmierung Segmentation fault bei Linux


von Erik (Gast)


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 !

von Ulrich (Gast)


Lesenswert?

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

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

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

Matthias

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

gdb deinprogramm
(gdb) run
[Fehlermeldung]
(gdb) backtrace

von Niquo (Gast)


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);

von A.K. (Gast)


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.

von Erik (Gast)


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 ?

von Andreas S. (andreas) (Admin) Benutzerseite


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:
1
MYSQL *mysql = NULL;

von A.K. (Gast)


Lesenswert?

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

von Erik (Gast)


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 ?!?

von Erik (Gast)


Lesenswert?

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

von FBI (Gast)


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:
1
MYSQL mysql;
2
mysql_init(&mysql);
oder:
1
MYSQL *pmysql;
2
pmysql = mysql_init(NULL);
3
if(!pmysql) {
4
  // ERROR
5
}
bzw.
1
MYSQL *pmysql = NULL;
2
pmysql = mysql_init(pmysql);
3
if(!pmysql) {
4
  // ERROR
5
}

CU Frank

von Erik (Gast)


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 !

von FBI (Gast)


Lesenswert?

>anderer segfault ...

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

CU

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.