Portierung eines C-Programms von SuSE 9.0 32bit auf openSuse 12.1 64bit -> SIGSEV
-
Wie sieht es aus, wenn du mal testweise mit -O0 kompilierst? Tritt der Fehler da auch auf? Neuere GCCs optimieren durchaus mal etwas aggressiver.
Ansonsten könnte das bei umfangreicherem Code eine längere Suche werden. Valgrind wäre da überaus hilfreich. Kannst du davon vielleicht eine eigene, nicht systemweit installierte, Kopie aus deinem Userverzeichnis starten? Ist zwar nicht besonders schön, aber nunja.
-
Wenn tmp ungültige Werte enthält bzw. auf unsinnige Speicherbereiche zeigt, dann nützt auch die Begrenzung der Feldbreite nichts.
-
gcc mit -O0 hat leider nicht geholfen.
Ich habe jettz einen segfault an einer Stelle, wo ein 2d-Char-Array mit 100x200 chars deklariert und initialisiert wird. Meint Ihr, das Problem liegt an einer Speicherbegrenzung? Ich habe wohlgemerkt aktuell noch 2 GB RAM frei beim Aufruf ...und das strlen im sprintf habe ich nur deshalb raus, weil bei mir size_t 8 byte und int 4 byte belegt. Nicht, dass da irgendwo was "verrutscht".
Soll ich jetzt noch alle "notes" und "warnings" rausmachen (1000 Stück) mit char * != unsigned char *?
-
Beim gcc ginge das auch einfach mit
-funsigned-char
Andere Compiler bieten sowas auch an.
-
Pretty schrieb:
Die Compilerwarnings sind mit -Wall sehr umfangreich und beziehen sich im Grunde ausschließlich auf die signedness Unterschiede bei Funktionsaufrufen mit char * / unsigned char *.
Was heißt denn im Grunde ausschließlich? Heißt das, es gibt da auch noch andere? Compilier mal auch noch mit -Wextra und -O3 (letzteres klingt zwar zunächst komisch, schmeißt aber in manchen Fällen Warnungen die man sonst nicht bekäme, weil der Code genauer analysiert wird). Und eventuell auch mal mit -Wno-sign-compare, um ein bisschen Übersicht zu behalten.
-
Ich bekomme nun noch einige Warnings beim Initialisieren von Strukturen...
programm.inc:1107: warning: missing initializer programm.inc:1107: warning (near initialization for 'ABC.attr1')
Ich bin davon ausgegangen, folgendes würde reichen:
struct ABC abc1 = {0}; struct ABC abc2[10] = { { 0 } }; struct ABC abc3[10][5] = { { { 0 } } };
Ist diese Notation für eine Initialisierung eher müllig? Dann tuts ja auch ein memset nach dem Deklarieren, oder? Die Strukturen haben teils 20 Attribute und ich möchte keine zeilenlangen Initialisierungsschlangen
-
Nochmal blöd gefragt:
Wenn size_t 8 byte braucht und int 4 byte, ich einer int Variable x den returnwert von strlen () zuweise (size_t!), ist das eher unpraktisch, oder?
-
Wie wäre es, das Programm erst einmal für 32bit zu bauen (-m32) und unter Suse 12.1 laufen zu laasen (ich geh mal davon aus, dass suse multilibfähig ist)? Wenn das funktioniert, kann man mit gutem Recht vermuten, dass aktuelle Libs nicht das Problem sind, sondern tatsächlich eine 64bit-Inkompatibilität vorliegt.
-
Ich gebe camper hier Recht, probier erstmal mit -m32 und schau, ob es da kompiliert wird.
Pretty schrieb:
Nochmal blöd gefragt:
Wenn size_t 8 byte braucht und int 4 byte, ich einer int Variable x den returnwert von strlen () zuweise (size_t!), ist das eher unpraktisch, oder?Nein, es sei denn, deine Zeichenkette hat eine Länge, die sich nicht mehr in einem int speichern lässt. Dann würde ein Datenverlust stattfinden (die zu vielen Bits würde einfach verworfen).
Aber da sich auch mit einem signed int 32 bit immerhin noch ca. 2 GB adressieren lassen, denke ich nicht, dass du da mit strlen Probleme bekommst
-
mit -m32 moniert mein gcc eine fehlende "stubs-32.h" in /usr/include/gnu/.
Dort liegt auch wirklich keine, dafür aber eine -64 und eine knapp halb so große stubs.hWie sage ich dem gcc, dass er die nehmen möge? ein linken der stubs.h auf stubs-32.h ist nicht möglich.
-
Die 32bit-Variante lässt sich also erstmal nicht so ohne weiteres kompilieren.
Habe gerade festgestellt, dass die Variablen, bei deren Initialisierung (Deklarierung geht natürlich) der SEGFAULT auftritt, in einem ziemlich "hohen" Speicherbereich, weg weg von anderen Daten des Programms liegen.
Kurz nach Programmstart, wird eine Variable xyz als Pointer auf ein Struktur-Array erzeugt und Speicher zugewiesen. Die Adresse des Pointers lautet dann "0x6a4d38".
Beim Segfault werden Speicherbereiche in folgendem Abschnitt berührt:
0x7fff3d1c6f50 etc...
Was ist das denn? Nimmt er sich nicht einfach Speicherbereiche, die irgendwo in der Nähe liegen?
-
Pretty schrieb:
Die 32bit-Variante lässt sich also erstmal nicht so ohne weiteres kompilieren.
Dann installier mal die Sachen die dafür nötig sind. gcc-multilib und die 32-Bit Version der glibc sind Stichworte, die dir helfen sollten. Bei Suse heißen die Pakete vermutlich leicht anders.
Es wäre jedenfalls schon einmal viel geholfen, wenn man weiß, ob das Programm einen allgemeinen Fehler hat, der durch moderne Compiler zum Vorschein kommt, oder ob das Programm sich fälschlicherweise auf etwas verlässt, dass nur für 32-Bit Systeme gilt.
Ist beides schlecht, aber es hilft bei der Fehlersuche. Von deiner Beschreibung her würde ich bis jetzt auf einen allgemeinen Fehler tippen. Programme mit derart vielen Compilerwarnungen machen auf mich keinen guten Eindruck.
Das mit dem "missing initializer" ist an sich harmlos, aber eventuell ist das Verhalten vom Programmierer nicht beabsichtigt. Der Compiler warnt, dass nicht alle Felder explizit initialisiert wurden, wodurch automatisch eine Nullinitialisierung der restlichen Felder erfolgt.
Habe gerade festgestellt, dass die Variablen, bei deren Initialisierung (Deklarierung geht natürlich) der SEGFAULT auftritt, in einem ziemlich "hohen" Speicherbereich, weg weg von anderen Daten des Programms liegen.
Kurz nach Programmstart, wird eine Variable xyz als Pointer auf ein Struktur-Array erzeugt und Speicher zugewiesen. Die Adresse des Pointers lautet dann "0x6a4d38".
Beim Segfault werden Speicherbereiche in folgendem Abschnitt berührt:
0x7fff3d1c6f50 etc...
Was ist das denn? Nimmt er sich nicht einfach Speicherbereiche, die irgendwo in der Nähe liegen?Dynamischer und statischer Speicher liegen traditionell sehr weit auseinander, denn in der Regel nimmt man das eine vom oberen und das andere vom unteren Ende des Adressraums.
Segfault bedeutet natürlich auf Deutsch, dass der berührte Speicher gar nicht gemappt ist, also dass dieser Pointer den du betrachtest ungültig ist, oftmals ist der dann nicht initialisiert.
-
Vielen Dank für die Erklärung, SeppJ!
gcc multilibfähig zu kompilieren wäre kein großes Hindernis - ist nur nicht gestattet.
Ich bin nun alle mir geläufigen Stellen im Programm durchgegangen, die prädestiniert dafür wären, Arraygrenzen zu überlaufen oder ähnliches.
Wenn der Compiler nun wenigstens noch meckern würde. Aber es knallt einfach beim Zugriff auf diesen Bereich im Speicher. Die Alternativ wäre nun noch, diese Arrays in Form von Pointern anzulegen und den Speicher zu allokieren. Mal sehn, ob das das Problem an eine Stelle schiebt, die offensichtlicher ist
-
Pretty schrieb:
gcc multilibfähig zu kompilieren wäre kein großes Hindernis - ist nur nicht gestattet.
Von wem? Deinem Arbeitgeber? Müsst ihr auch mit verbundenen Augen und der rechten Hand auf dem Rücken arbeiten?
Hast du mal valgrind oder ähnliches auf das Problem angesetzt? Wozu von Hand suchen und raten, wenn ein Computer fehlerfrei alles durchtesten kann?
-
Ich komme von C# und wurde hier in eine steinzeitliche Grube geworfen, in der Windows verteufelt und alle Hilfsmittel dieses Jahrtausends verschmäht werden.
Deshalb darf ich auf einem 10 Jahre alten Betriebssystem (das nicht angepasst werden darf und kann) entwickeln und das Ergebnis dann auf ein aktuelles System schmeißen.
Meine spärlich vorhandenen C-Kenntnisse mische ich täglich mit einer Portion Phantasie und Mut und erzeuge daraus teils kompilierbaren Code. Aber das nur zum Thema Arbeitgeber. Ich bin froh, diesen Job zu haben und möchte das Beste draus machen. Mit den Mitteln, die ich eben zur Verfügung habe...
-
valgrind läuft ja leider nicht. Steht denke ich in meinem ersten Post. Valgrind ist installiert, bricht aber ab, weil die debuginfos bzw. das jeweilige Paket fehlt. gdb meckert auch reichlich, aber ist gnädiger und läuft wenigstens.
-
Kannst du dir da nicht einen gcc im $HOME Verzeichnis kompilieren?
-
auf meinem 32bit-System und mit einem Valgrind aus der Vorkriegszeit bekomme ich im Übrigen keine signifikanten Probleme gemeldet. Ein Speicherproblem mit uninitialisierten Variablen in einer shared lib vom Kollegen hat er angeblich ausgebessert - kann ich nicht nachvollziehn, weil er nur eine 64-bit-Version der lib für besagte Maschine gebaut hat und dort ja kein valgrind läuft...
-
Pretty schrieb:
auf meinem 32bit-System und mit einem Valgrind aus der Vorkriegszeit bekomme ich im Übrigen keine signifikanten Probleme gemeldet. Ein Speicherproblem mit uninitialisierten Variablen in einer shared lib vom Kollegen hat er angeblich ausgebessert - kann ich nicht nachvollziehn, weil er nur eine 64-bit-Version der lib für besagte Maschine gebaut hat und dort ja kein valgrind läuft...
Keine signifikanten Probleme? Angeblich ausgebessert? Jedes Problem das valgrind meldet ist fast ausnahmslos äußerst signifikant. Ich habe den Eindruck, dass das Problem hier das laxe Verhalten bei Fehlern und Warnungen ist. Hauptsache es läuft, oder? Da siehst du, wohin diese Einstellung führt.
Das schöne an deinem vorsinntflutlichen Betriebssystem ist doch, dass du dir den neuesten gcc und das neueste valgrind und die Multilib und alle Abhängigkeiten einfach in dein Homeverzeichnis installieren kannst. Dann bei jedem configure das Homeverzeichnis als Include-/Lib-/Runpfad angeben. Oder einfach für dich diese Pfade fest in die entsprechenden Umgebungsvariablen schreiben. Und schon hast du alles was du brauchst, mit dem gleichen Komfort als sei es systemweit installiert. Versuch das mal in Windows oder mit einer Klickibunti-IDE .
(Es dürfte jedoch ein paar Stunden dauern, den GCC, valgrind und die multilib aus dem nichts zu compilieren. Da muss man dann eben durch)
P.S.: Und wie kann valgrind kein Problem melden, wenn das Programm abstürzt? Es sollte dir im Gegenteil sogar die Ursache melden, im Idealfall sogar zurückverfolgt bis an die Stelle der eigentlichen(!) Ursache, die zu dem unmittelbaren Absturz geführt hat. Irgendwas stimmt hier doch nicht.
-
SeppJ schrieb:
(Es dürfte jedoch ein paar Stunden dauern, den GCC, valgrind und die multilib aus dem nichts zu compilieren. Da muss man dann eben durch)
Das dauert bei mir wahrscheinlich noch länger, wenn ich keine idiotensichere Anleitung finde
SeppJ schrieb:
P.S.: Und wie kann valgrind kein Problem melden, wenn das Programm abstürzt? Es sollte dir im Gegenteil sogar die Ursache melden, im Idealfall sogar zurückverfolgt bis an die Stelle der eigentlichen(!) Ursache, die zu dem unmittelbaren Absturz geführt hat. Irgendwas stimmt hier doch nicht.
Valgrind läuft ja auf dem 64bit-System noch nicht, also meldet es dort nichts. Auf dem 32-Bit-System gibt es keinen Absturz. Die ausgespuckten Meldungen beziehen sich alle auf die nicht debugfähige shared lib vom Kollegen, der die Probleme ja behoben habe.
Jetzt such ich mal nach einer Möglichkeit, meinen GCC auf der 32bit-Maschine lokal aktuell zu halten.