Speicherzugriffsfehler nur bei gcc amd_64 nicht i386

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
mgolbs
Beiträge: 259
Registriert: 22.03.2009 18:08:17
Wohnort: Tirschenreuth - Löbau

Speicherzugriffsfehler nur bei gcc amd_64 nicht i386

Beitrag von mgolbs » 12.03.2014 13:38:38

Hallo,

habe einen Quellecode der unter i386 mit gcc prima funktioniert. Unter amd_64 kommt ein Speicherzugriffsfehler. Ich habe den Code analysiert und bin auf die Stelle gestoßen, welche Probleme macht:

Code: Alles auswählen

....
  int libsmtp_int_bytes;
  char libsmtp_int_rec_buffer[4096];
  char *libsmtp_int_temp_buffer=NULL;
       printf("libsmtp_int_temp_buffer: %p\n",&libsmtp_int_temp_buffer); 
       printf("libsmtp_int_temp_buffer: %s\n",libsmtp_int_temp_buffer);  
... 
funktioniert noch.

Code: Alles auswählen

...
int libsmtp_int_read (GString *libsmtp_gstring_read, struct libsmtp_session_struct *libsmtp_session, int type)
{
  int libsmtp_int_bytes;
  char libsmtp_int_rec_buffer[4096];
  char *libsmtp_int_temp_buffer=NULL;
..
..
..
 libsmtp_int_temp_buffer = strtok (libsmtp_int_rec_buffer, " ");
 printf(" Adresse ist %p\n",&libsmtp_int_temp_buffer);  
 printf ("Inhalt ist %s\n",libsmtp_int_temp_buffer);
....
.... 
libsmtp_int_temp_buffer: 0x7fffc52e36a8
libsmtp_int_temp_buffer: (null)
libsmtp_int_rec_buffer 1: 220 mx.klm-rtz.com ESMTP SonicWALL (xxxxxx)

Speicherzugriffsfehler
Die Adresse der Variable kann ich auslesen. libsmtp_int_rec_buffer enthält eine Zeichenkette .Wenn ich den Inhalt von libsmtp_int_temp_buffer anzeigen lassen will gibt es einen Speicherzugriffsfehler, aber nur unter amd_64 nicht unter i386. Nur strtok() nutze ich davor. Da, strtok(), kann doch kein Unterschied zwischen amd_64 und i386 sein?

Da ich leider kein Fachmann bin würde ich mich über Tipps freuen.

Gruß und Dank Markus
Dem Überflüssigen nachlaufen, heißt das Wesentliche verpassen.
Jules Saliège

newdeb
Beiträge: 134
Registriert: 03.02.2011 11:11:21
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Frankfurt

Re: Speicherzugriffsfehler nur bei gcc amd_64 nicht i386

Beitrag von newdeb » 12.03.2014 14:10:08

Tipp Nr. 1: Returnwert prüfen:

Code: Alles auswählen

if ((libsmtp_int_temp_buffer = strtok (libsmtp_int_rec_buffer, " ")) != NULL) {
    printf(" Adresse ist %p\n",&libsmtp_int_temp_buffer); 
    printf ("Inhalt ist %s\n",libsmtp_int_temp_buffer);
}

mgolbs
Beiträge: 259
Registriert: 22.03.2009 18:08:17
Wohnort: Tirschenreuth - Löbau

Re: Speicherzugriffsfehler nur bei gcc amd_64 nicht i386

Beitrag von mgolbs » 12.03.2014 14:49:09

Hallo,

vielen Dank! Returnwert ist NULL, kein printf("...

Gruß und Dank Markus
Dem Überflüssigen nachlaufen, heißt das Wesentliche verpassen.
Jules Saliège

wanne
Moderator
Beiträge: 7462
Registriert: 24.05.2010 12:39:42

Re: Speicherzugriffsfehler nur bei gcc amd_64 nicht i386

Beitrag von wanne » 12.03.2014 14:58:12

mgolbs hat geschrieben:Die Adresse der Variable kann ich auslesen. libsmtp_int_rec_buffer enthält eine Zeichenkette
Ist die auch sicher NULL-terminiert? Da psst auch strtok rein: http://natashenka.ca/wp-content/uploads ... t11x17.pdf
mgolbs hat geschrieben:Wenn ich den Inhalt von libsmtp_int_temp_buffer anzeigen lassen will gibt es einen Speicherzugriffsfehler, aber nur unter amd_64 nicht unter i386. Nur strtok() nutze ich davor. Da, strtok(), kann doch kein Unterschied zwischen amd_64 und i386 sein?
Speicherallocation unter C ist böse: Wenn du auf dem Stack speicher allozierst bekommst du einen block unbekannter größe und Inalts. Z.B. könnten in deinem libsmtp_int_rec_buffer 4096 Zeichen stehen. In deinem i386 Programm bekommst du zufällig einen Block der etwas größer ist und direkt danach eine NULL hat. Kein Problem. Du hast genau die Zeichen, die du reingeschrieben hast als String. In dem amd64 programm sind danach ein paar Zeichen die nicht NULL sind und danach ist der Stack aus. => Speicherzugriffsfehler.

Alternativ: Was eher auf deine NULL rückgabe spricht: Du hast zufällig ein 0x20 in deiem i386 Speicher stehen. Damit funktioniert dein strtok ein mal öfter. In deim amd64 programm ist da stattdessen eine NULL. => strtok returnt NULL.
rot: Moderator wanne spricht, default: User wanne spricht.

mgolbs
Beiträge: 259
Registriert: 22.03.2009 18:08:17
Wohnort: Tirschenreuth - Löbau

Re: Speicherzugriffsfehler nur bei gcc amd_64 nicht i386

Beitrag von mgolbs » 12.03.2014 15:26:01

Hallo,

vielen Dank für die Rückmeldung. Das Programm unter i386 habe ich auf verschiedenen Rechnern unter verschiedenen 32bit i386 über ./configure und make erstellt, ausprobiert und keinerlei Probleme festgestellt. Habe mal libsmtp_int_rec_buffer mit \0 zum Test bei [19] abgeschlossen, gleiches Problem. Dann habe ich mal die Größe von:

Code: Alles auswählen

char libsmtp_int_rec_buffer[20];
verkleinert, aktiv abgeschlossen und habe gleiches Problem. Habe auch mal ein reichliches malloc() auf libsmtp_int_temp_buffer gemacht mit gleichem Effekt - Speicherzugriffsfehler.

Gruß und Dank Markus
Dem Überflüssigen nachlaufen, heißt das Wesentliche verpassen.
Jules Saliège

newdeb
Beiträge: 134
Registriert: 03.02.2011 11:11:21
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Frankfurt

Re: Speicherzugriffsfehler nur bei gcc amd_64 nicht i386

Beitrag von newdeb » 12.03.2014 16:24:38

Bitte auch die Codeabschnitte posten, die
  • - den Buffer libsmtp_int_rec_buffer füllen
    - und die Ausgabe machen:
    libsmtp_int_rec_buffer 1: 220 mx.klm-rtz.com ESMTP SonicWALL (xxxxxx)

mgolbs
Beiträge: 259
Registriert: 22.03.2009 18:08:17
Wohnort: Tirschenreuth - Löbau

Re: Speicherzugriffsfehler nur bei gcc amd_64 nicht i386

Beitrag von mgolbs » 12.03.2014 16:52:59

Hallo,

bin ein Stück weiter gekommen. strtok on 64 bit machines http://stackoverflow.com/questions/9370 ... t-machines habe nun die #include "string.h" mit drin und es läuft. Leider verstehe ich den Hintergrund noch nicht wirklich. Nun kämpfe ich noch mit dem Exchange SMTP. Am SMTP meines Providers funktioniert der Code schon.

Gruß und Dank Markus
Dem Überflüssigen nachlaufen, heißt das Wesentliche verpassen.
Jules Saliège

wanne
Moderator
Beiträge: 7462
Registriert: 24.05.2010 12:39:42

Re: Speicherzugriffsfehler nur bei gcc amd_64 nicht i386

Beitrag von wanne » 12.03.2014 23:53:02

bin ein Stück weiter gekommen. strtok on 64 bit machines http://stackoverflow.com/questions/9370 ... t-machines habe nun die #include "string.h" mit drin und es läuft.
Nein, das hat absolut gar nichts damit zu tun. Der hat ein paar mehr Sachen falsch gemacht und bei dem typischen -Wall -Werror hätte ihm der Compiler das auch garantiert nicht mehr compiliert. AUch wenn du das anders viel schöner fändest. Dein Programm ist kaputt und zwar aller wahrscheinlichkeit nach auch die 32Bit version. Nicht strtok. Und am Internet hat sowas besser gar nichts verloren. Überlege dir ernsthaft ob du nicht lieber erstmal in Java schreibst, wenn du jetzt schnell was fertig bringen willst. Da kann man einfach wesentlich weniger falsch machen.
rot: Moderator wanne spricht, default: User wanne spricht.

newdeb
Beiträge: 134
Registriert: 03.02.2011 11:11:21
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Frankfurt

Re: Speicherzugriffsfehler nur bei gcc amd_64 nicht i386

Beitrag von newdeb » 13.03.2014 12:51:36

wanne hat geschrieben:Nein, das hat absolut gar nichts damit zu tun.
Würde ich jetzt so nicht behaupten. Lässt sich auch einfach nachstellen:

Code: Alles auswählen

#include <stdio.h>
int main() {
	char buf[] = "foo bar";
	char *pbuf;
	
	printf("Buffer location: %p\n", (void *)buf);
	if ((pbuf = strtok(buf, " ")) != NULL) {
		printf("First token: %p\n", (void *)pbuf);
		printf("Cast to int: %#x\n", (int)pbuf);
		printf("Now print buffer:\n");
		printf("%s\n", pbuf);
	}
	return 0;
}
Ohne -Werror kompiliert gcc das Programm, auch ohne inkludiertes <string.h>.

Ergebnis auf 32 Bit-Maschine:

Code: Alles auswählen

Buffer location: 0xbfbd4e04
First token: 0xbfbd4e04
Cast to int: 0xbfbd4e04
Now print buffer:
foo
Ergebnis auf 64 Bit-Maschine:

Code: Alles auswählen

Buffer location: 0x7fffd3dccee0
First token: 0xffffffffd3dccee0
Cast to int: 0xd3dccee0
Now print buffer:
Speicherzugriffsfehler (Speicherabzug geschrieben)
Die 4 oberen Byte des 64bit-Pointers bleiben uninitialisiert, was die Zugriffsverletzung zur Folge hat.

wanne
Moderator
Beiträge: 7462
Registriert: 24.05.2010 12:39:42

Re: Speicherzugriffsfehler nur bei gcc amd_64 nicht i386

Beitrag von wanne » 13.03.2014 13:44:54

Wie du sihst würde pbuf bei dem Fehler mit an sicherheit grenzender Wahrscheinlichkeit nie null. (Eigentlich gar nicht aber irgend wie mach Linux komische sachen mit dem Anfang vom Stack. Pseudo-random stack pointer nennt sich das glaube ich.)
rot: Moderator wanne spricht, default: User wanne spricht.

Antworten