Bus Error - wer erklärt mir das?



  • hey forum,
    also ich hab ein problem, bin quasi c-anfänger, werde die sprache aber fürs studium benötigen und habe mich deshalb dran gesetzt übungen nachzumachen. hier mein code den ich bisher für die aktuelle aufgabe verfasst habe:

    #include <stdio.h>
    #include <stdlib.h>
    
    void eingabe(double *p, int zeile, int spalte);
    void ausgabe(double *p, int zeile, int spalte);
    
    int main(void){
    	int z, s;
    	double *Pointer, *ptr;
    	int i=0;
    	int eing;
    
    	printf("\nBitte Anzahl Zeilen angeben: ");
    	scanf("%d",&z);
    	printf("\nBitte Anzahl Spalten eingeben: ");
    	scanf("%d",&s);
    	printf("\n\n");
    
    	Pointer = (double *) malloc(s * z * sizeof(double));
    
    	printf("\nZeigerdeklarierung fluppt!!\n");
    
    	if (Pointer = NULL) {
    		printf("problem mim speicher!\n");
    	}
    
    	for (i=1, ptr = Pointer; i<=s*z; i++, ptr++){
    		*ptr = 0.;
    	}// FEHLER ist in dieser for-schleife, wenn ich als zeilen und spalten etwas groesser 1 verwende schmiert es ab mit fehlermeldung: "Bus Error"
    
    	printf("\nInitialisierung mit nullen fluppt!!\n");
    
    	do {
    		eingabe(Pointer, z, s);
    		ausgabe(Pointer, z, s);
    		printf("\nWeiter mit 1, zum beenden 0.\n");
    		scanf("%d",&eingabe);
    
    	} while (eing == 1);
    
    }
    
    void eingabe(double *p, int zeile, int spalte){
    	int s,z;
    	double wert;
    	double *pzs;
    	printf("\nZeile bitte!\n");
    	scanf("%d",&z);
    	printf("\nSpalte bitte! \n");
    	scanf("%d",&s);
    	pzs = p + (z-1) * zeile + s - 1;
    	printf("\nWert a! aber zackig!\n");
    	scanf("%lf",pzs);
    	printf("Gespeichert ab adresse %p \n",pzs);
    
    }
    
    void ausgabe (double *p, int zeile, int spalte){
    	int i,j;
    	for (i=0;i<zeile;i++){
    		for (j=0;j<spalte;j++){
    			printf("\ni*s + j= %2d   Adresse: %p   ",i*spalte +j,p+ i*spalte + j);
    			printf("  Element [%d][%d] = %12lf",i,j,p);
    		}
    	}
    }
    

    kompiliere übrigens unter OS X mim gcc



  • necromant schrieb:

    if (Pointer = NULL) { // XXX
    		printf("problem mim speicher!\n");
    	}
    	
    	for (i=1, ptr = Pointer; i<=s*z; i++, ptr++){
    		*ptr = 0.;
    	}// FEHLER ist in dieser for-schleife, wenn ich als zeilen und spalten etwas groesser 1 verwende schmiert es ab mit fehlermeldung: "Bus Error"
    

    An der von mir mit XXX markierten Stelle weist du Pointer den Wert 0 zu, in der Schleife versuchst du dann an diese Speicherstelle etwas zu schreiben. Das Dereferenzieren eines Nullzeigers ist aber undefiniert, und moderne Betriebssysteme reagieren darauf in der Regel allergisch.

    Du meintest wahrscheinlich if (Pointer == NULL).

    BTW, nach der Speicherfehlermeldung wär eine Art Programmabbruch ganz sinnvoll.



  • Hi!

    Ja, du solltest das Programm mit einem exitcode verlassen:

    if (!Pointer) {
      perror("Es konnte keine Speicher allokiert werden!\n");
      exit(1);
    }
    

    Außerdem musst du den mit malloc allokierten Speicher am Ende der Funktion wieder freigeben mit "free(Pointer);".

    Code-Hacker



  • Code-Hacker schrieb:

    Außerdem musst du den mit malloc allokierten Speicher am Ende der Funktion wieder freigeben mit "free(Pointer);".

    Das ist bei so kurzen Programmen, die sich nach der Berechnung beenden, eher Ansichtssache.



  • Hi!

    Ansichtssache? Wieso sollte das Ansichtssache sein?
    Dynamisch allokierter Speicher sollte auch richtig wieder freigegeben werden. Ansonsten hast du Speicherlecks. Und dabei ist die Programmlänge völlig egal. Speicher den du allokierst musst du auch wieder freigeben, also, zu jedem malloc gehört ein free.

    Ich hoffe nur das es nicht viele Programmierer gibt die dies als Ansichtssache sehen (unabhängig von der Programmlänge), es ist nämlich falsch. Immerhin ist der Speicher dann nicht mehr nutzbar und wenn ich das Programm durch ein anderes Programm mehrere Millionen male aufrufe (z.B. Server im Dauerbetrieb oder so) habe ich irgendwann keinen Speicher mehr, da keiner freigegeben wurde von diesem Programm.

    Code-Hacker



  • Hmmm manchmal hab ich das Gefühl, dass es bei Win98 Ansichtssache war mit dem free() 😉

    Ansonsten schließ ich mich dem hier an:

    Code-Hacker schrieb:

    zu jedem malloc gehört ein free.



  • Falsch, der von malloc allozierte Speicher ist eine interne Resource des Programms, das Betriebssystem* interessiert sich dafür idR nicht und räumt einfach alles weg, was das Programm belegt hat. Das zwanghafte Speicherfreiräumen am Ende des Programms führt bei größeren Programmen dazu, dass Speicher, der lange nicht benutzt wurde, wieder von der Platte eingelagert werden muss, nur um ihn freizugeben. Das Problem ist: In der Regel hat man keine andere Wahl, vom Software-Engineering-Standpunkt aus gesehen, weil es sehr schwer ist, Programmteile, die nicht wieder aufräumen, wiederzuverwenden. Also beißt man in den sauren Apfel, und gibt grundsätzlich alles wieder frei.
    Eine Lösung dagegen heißt Garbage Collector, der gibt nämlich entgegen landläufiger Ansicht nicht unbenutze Blöcke frei, sondern behält die benutzen Blöcke.

    (*) ich rede hier von modernen Betriebssystemen und kooperativen malloc-Implementierungen. Es steht natürlich einem DOS-Compilerbauer frei, malloc mithilfe von DOS-API 0x48 zu implementieren.



  • Hi!

    Ok, das mag bei malloc so sein. Ich gebe zu das was ich geschrieben habe, habe ich aus den Delphi-Vorlesungen behalten und habe es mir selbst schon immer eingetrichtert zu jedem new ein delete und zu jedem malloc ein free zu schreiben. Dann kann sicher nichts daneben gehen.
    Gott sei dank muss ich nach diesem Semester C (ansi 89) nicht mehr anfassen *g* (bleibe lieber bei C++).

    Code-Hacker



  • Bei Mozilla sieht man sehr drastisch, was passiert, wenn am Ende alles freigegeben wird (wenn er inzwischen auf die Platte ausgelagert wurde). Würde er sich einfach beenden, wäre er in 0.x Sekunden weg. So rattert er aber 15 Sekunden nutzlos herum.


Anmelden zum Antworten