Speicher Fehler (etwas größeres Problem)



  • Hi, ich programmiere seit 3 Monaten und das ist mein ersten eigenständiges
    programm, der rest war immer hausarbeit beim studium.

    Also das Programm ruft ein Fehler mit einer Speicheradresse auf, aber nur im
    debuggmodus, nur leider kenn ich mich nicht wirklich damit aus.

    Das Programm ließte eine 450megabyte datei Zeilenweise ein bearbeiten sie bis sie
    einen Datensatz zusammenhat und schreibt die neue formatierte zeile wieder in
    eine Datei.

    Also ohne diesen obrigen teil, also die 3 Funktionen da, funktioniert das teil.
    allerdings ist dass das wichtigste sie formatiert die zeilen.
    ChangeInetnum()
    ChangeTdescr()
    ChangeTchanged()
    also ausgeben muss sie 120 megabyte diese bricht immer nach 14 ab.
    wenn ich changeInetnum rausnehme sinds 74 megabyte, alle 3 draußen funktionierts wie ich will, nur halt ohne formatierung.

    Die File ist wie gesagt sehr groß und mich intersieren auch nur ein paar bestandteile davon. außerdem ist die formatierung oder anzahl unterschiedlich.
    aber das funktioniert alles

    ES MUSS was mit dem speicher zu tun haben, malloc oder so, haber das aber nicht
    hinbekommmen, hoffe Ihr könnt mir da weiter helfen.

    DAS PROGRAMM FUNKTIONIERT ANSONSTEN.

    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <string.h>
    #define BUFSIZE 255                    //Buffer für die aktuelle Zeile zum Bearbeiten
    #define BUFSIZE2 127							//Buffer für die einzelnen Items
    
    long int FileSize(FILE *dataO)			//Größe der Datei Bestimmen
    {
    	long int Size;
       fseek( dataO, 0, SEEK_END );			//Springt ans Ende Der Datei
    	Size = ftell(dataO);      			   //Ermittelt Größe
       fseek( dataO, 0, SEEK_SET );        //Springt wieder an Anfang (Wichtig!)
       return Size;
    }
    
    void ChangeInetnum(char *pTinetnum)				 		//"-" rausnehmen und dafür Tab einsetzen
    {
    	char *ptemp, *ptemp2;
       for(ptemp=pTinetnum;*ptemp!=' ';ptemp++){												  //Bis zur ersten Leerstelle springen
       	;
       }
       for(ptemp2=ptemp;((int)*ptemp2)<48||((int)*ptemp2)>57;ptemp2++){             //Ab Leerstelle bis zur ersten Zahl-
       	;                                                                         //mit casting (int) ermittelt
       }
       *ptemp++='\t';
       *ptemp='\t';                                                                 //2 Tab zwischen die IPs
       ptemp++;
       while(*ptemp2!='\n'){
       	*ptemp=*ptemp2;
          ptemp++;
          ptemp2++;
       }
       *ptemp++='\n';                                                               //hinten NewLine
       *ptemp='\0';                                                                 //und Ende dran
    
    }
    
    void ChangeTdescr(char *pTdescr)						  	  //Begrenzen auf 100 Stellen
    {
    	char *ptemp;
       int i=0;
       for(ptemp=pTdescr;*ptemp!='\n';ptemp++,i++){                                 //Bis Ende des Items zählen
       	;
       }
       if(i>100){                                                                   //Zähler über 100
       	ptemp=pTdescr;                                                            //Wenn ja "Ende" hier setzen!
          ptemp+=100;
          *ptemp++='\n';
          *ptemp='\0';
       }else
       	;
    }
    
    void ChangeTchanged(char *pTchanged)						//Alles hinter Leerzeichen abtrennen
    {
    	char *ptemp;
       for(ptemp=pTchanged;*ptemp!=' ';ptemp++){
       	;
       }
       *ptemp++='\n';
       *ptemp='\0';
    }
    
    																		//Alle Items zu einer Zeile zusammenfügen (2Tabs getrennt)
    void CompleteLine(char *pFinalLine,char *pTinetnum, char *pTnetname, char *pTdescr, char *pTcountry, char *pTchanged)
    {
    	char *pFinalZeiger, *pItemZeiger;
       pFinalZeiger=pFinalLine;
    
    	for(pItemZeiger=pTinetnum;*pItemZeiger!='\n';pItemZeiger++,pFinalZeiger++){
       	*pFinalZeiger=*pItemZeiger;
       }
       *pFinalZeiger++='\t';
       *pFinalZeiger++='\t';
    	for(pItemZeiger=pTnetname;*pItemZeiger!='\n';pItemZeiger++,pFinalZeiger++){
       	*pFinalZeiger=*pItemZeiger;
       }
       *pFinalZeiger++='\t';
       *pFinalZeiger++='\t';
       for(pItemZeiger=pTdescr;*pItemZeiger!='\n';pItemZeiger++,pFinalZeiger++){
       	*pFinalZeiger=*pItemZeiger;
       }
       *pFinalZeiger++='\t';
       *pFinalZeiger++='\t';
       for(pItemZeiger=pTcountry;*pItemZeiger!='\n';pItemZeiger++,pFinalZeiger++){
       	*pFinalZeiger=*pItemZeiger;
       }
       *pFinalZeiger++='\t';
       *pFinalZeiger++='\t';
       for(pItemZeiger=pTchanged;*pItemZeiger!='\n';pItemZeiger++,pFinalZeiger++){
       	*pFinalZeiger=*pItemZeiger;
       }
       *pFinalZeiger++='\n';
       *pFinalZeiger='\0';
    }
    
    void DatenSatz(FILE *dataO, FILE *dataW)
    {
    	int i, j;
       bool a,b,c,d,e;
       a=b=c=d=e=false;
    
       char FileBuffer[BUFSIZE];						//Zeile die Bearbeitet wird
       char FinalLine[BUFSIZE2*5];               //Bearbeite Zeile die am Ende geschrieben wird
       char *pFinalLine=FinalLine;               //Zeiger für ^^
    
    	char Sinetnum[]="inetnum:";               //Suchbegriffe für der einzelnen Items
       char Snetname[]="netname:";
       char Sdescr[]="descr:";
       char Scountry[]="country:";
       char Schanged[]="changed:";
    
       char Tinetnum[BUFSIZE2]; 						//Variablen für die einzelnen Items
       char Tnetname[BUFSIZE2];
       char Tdescr[BUFSIZE2];
       char Tcountry[BUFSIZE2];
       char Tchanged[BUFSIZE2];
    
       char *pTinetnum=Tinetnum;						//Zeiger für die einzelnen Items
       char *pTnetname=Tnetname;
       char *pTdescr=Tdescr;
       char *pTcountry=Tcountry;
       char *pTchanged=Tchanged;
    
       //Durchlaufen der Datei vom Anfang bis zum Ende
    	while((fgets(FileBuffer,sizeof(FileBuffer),dataO))!=NULL){
          //Wenn NewLine auftritt setze den Datensatz "Changed:" auf fertig
          //auf Item:"Changed" bezogen damit Changed den letzten Wert erhält (neuste)
          //Alle anderen Items jeweils den ersten Wert
       	if(FileBuffer[0]=='\n'){
             e=true;
          }else
          	;
          //Prüfen ob alle Items einen Wert bekommen haben
        	if((a==true)&&(b==true)&&(c==true)&&(d==true)&&(e==true)){
          	ChangeInetnum(pTinetnum);						//Veränderung des IP-Items (siehe oben)
             ChangeTdescr(pTdescr);                    //Veränderung der Beschreibung (siehe oben)
             ChangeTchanged(pTchanged);                //Veränderung des ChangedItems (siehe oben)
             //Funktionsaufruf zum zusammenstellen der zu schreibenen Zeile
             CompleteLine(pFinalLine,pTinetnum,pTnetname,pTdescr,pTcountry,pTchanged);
             //Schreiben der zusammengestellten Zeile (Ein Datensatz fertig)
             fputs(FinalLine, dataW);
             //Alle Werte als unbeabeitet markieren
             a=b=c=d=e=false;
             //Neuer Datensatz wird somit bearbeitet
          }else
          	;
    
       	if((strstr(FileBuffer,Sinetnum) != 0)&&a==false){				//"inetnum:" enthalten?
          	for(i=14,j=0;FileBuffer[i]!='\n';i++,j++){               //ab 14. Stelle Variable füllen
       			Tinetnum[j]=FileBuffer[i];
             }
             Tinetnum[j]='\n';
             Tinetnum[j+1]='\0';
             a=true;
    
          }else if((strstr(FileBuffer,Snetname) != 0)&&b==false){		//"netname:" enthalten ?
          	for(i=14,j=0;FileBuffer[i]!='\n';i++,j++){               //ab 14. Stelle Variable füllen
       			Tnetname[j]=FileBuffer[i];
             }
             Tnetname[j]='\n';
             Tnetname[j+1]='\0';
             b=true;
    
          }else if((strstr(FileBuffer,Sdescr) != 0)&&c==false){			//"descr:" enthalten ?
          	for(i=14,j=0;FileBuffer[i]!='\n';i++,j++){               //ab 14. Stelle Variable füllen
       			Tdescr[j]=FileBuffer[i];
             }
             Tdescr[j]='\n';
             Tdescr[j+1]='\0';
             c=true;
    
          }else if((strstr(FileBuffer,Scountry) != 0)&&d==false){		//"country:" enthalten ?
          	for(i=14,j=0;FileBuffer[i]!='\n';i++,j++){               //ab 14. Stelle Variable füllen
       			Tcountry[j]=FileBuffer[i];
             }
             Tcountry[j]='\n';
             Tcountry[j+1]='\0';
             d=true;
    
          }else if((strstr(FileBuffer,Schanged) != 0)){               //"changed:" enthalten ?
          	for(i=14,j=0;FileBuffer[i]!='\n';i++,j++){               //ab 14. Stelle Variable füllen
       			Tchanged[j]=FileBuffer[i];
             }
             Tchanged[j]='\n';
             Tchanged[j+1]='\0';
          }else{																	   //Wenn nichts davon enthalten
          	;                                                        //nächste Zeile bearbeiten
          }
       }
    }
    
    int main ()
    {
    	FILE *dataO, *dataW;
       char FileOpen[255]="testripe2.db";
       char FileWrite[255]="testripeW.db";
       long int Size;
    
       //Dateien Öffnen
       dataO=fopen(FileOpen, "r");
       dataW=fopen(FileWrite, "w+");
    
       //Größe der Datei Bestimmen
       Size=FileSize(dataO);
       printf("%i Bytes\n", Size);
    
       //Prüfen der Datei zum Lesen
       if(!dataO){
       	printf("Fehler beim Öffnen der Datei: %s\n",FileOpen);
          getch();
          return 0;
       }else
       //Prüfen der Datei zum Schreiben
    		if(!dataW){
       		printf("Fehler beim Anlegen der Datei: %s\n",FileWrite);
       		getch();
       		return 0;
          }else
          	;
       //Aufruf der Funktion zum Bearbeiten
       DatenSatz(dataO, dataW);
    
       //Dateien schließen
       fclose(dataO);
       fclose(dataW);
    
       printf("Fertig\n");
       getch();
    }
    


  • auszug aus der datei die bearbeit wird, (testripe.db)
    das funktiniert auch, erst ab großer mb zahl nicht mehr

    inetnum:      80.16.151.180 - 80.16.151.183
    netname:      NETECONOMY-MG41731
    descr:        TELECOM ITALIA LAB SPA
    country:      IT
    admin-c:      TILS2-RIPE
    tech-c:       TILS2-RIPE
    status:       ASSIGNED PA
    notify:       neteconomy.rete@telecomitalia.it
    mnt-by:       INTERB-MNT
    changed:      neteconomy.rete@telecomitalia.it 20010824
    source:       RIPE
    
    inetnum:      213.95.6.32 - 213.95.6.47
    netname:      STAEDTLER-MARS-NET
    descr:        STAEDTLER MARS GmbH & Co.
    descr:        Moosaeckerstrasse 3
    descr:        D-90427 Nuernberg
    country:      DE
    admin-c:      TS15310-RIPE
    admin-c:      GW6406-RIPE
    admin-c:      JF7805-RIPE
    admin-c:      SE4158-RIPE
    tech-c:       NNN-RIPE
    status:       ASSIGNED PA
    notify:       guardian@noris.net
    mnt-by:       NORIS-MNT
    changed:      thomas@noris.net 20001110
    changed:      fany@noris.net 20001110
    changed:      fany@noris.net 20010507
    changed:      fany@noris.net 20010523
    source:       RIPE
    
    inetnum:      213.56.169.22 - 213.56.169.22
    netname:      FR-COBIPORC
    descr:        COBIPORC
    descr:        BP 2 - le Val
    descr:        35590           Saint Gilles
    country:      FR
    admin-c:      VL2000-RIPE
    tech-c:       VL2000-RIPE
    tech-c:       OH251-RIPE
    status:       ASSIGNED PA
    mnt-by:       OLEANE-NOC
    changed:      hostmaster@oleane.net 20010611
    source:       RIPE
    
    inetnum:      80.16.85.128  - 80.16.85.143
    netname:      MAXIMA
    descr:        MAXIMA SRL
    country:      IT
    admin-c:      AA7976-RIPE
    tech-c:       AA7976-RIPE
    status:       ASSIGNED PA
    notify:       network@cgi.interbusiness.it
    mnt-by:       INTERB-MNT
    changed:      network@cgi.interbusiness.it 20010911
    source:       RIPE
    


  • Lern debuggen 😡

    BTW: Dein RAM ist wahrscheinlich zu klein.



  • das ist doch nur keine lösung, das muss man doch auch mit wenig ram
    erledigen können, der ließt ja lediglich ne zeile und und schreibt wieder rein.
    während der laufzeit frißt das programm 700kb. also daran liegt es dann wohl
    nicht, am ende ist der speicher mal kurz 1200kb groß.



  • Hab das "zeilenweise" überlesen. Dann lern debuggen.



  • Mit valgrind kann man den Speicher eines Programms (ist echt gut) untersuchen, ich weiß aber nicht, ob's ne windows Portierung gibt. Sonst wie meiner Vorgänger: Lerne debuggen, du kannst nicht von uns verlangen, dass wir die Arbeit eines Debuggers machen, oder?



  • so hab nochmal getestet, also wenn ich die obere funktion rausnehme debugge
    ist er an addrees 0x0, da ist wohl schluss, bei allem schreibt er ja nur 14mb
    da ist bei 0909090 schluss. kann man nicht immer ein stück bearbeiten oder wie
    versteh das nicht,



  • zeilenweise den code durchgehen!
    dh:
    von der main angefangen, immer die exit(0); funktion eine zeile nach unten tun, bis du den fehler lokalisieren konntest 🙂
    so in der art machs ich halt. dazu jede menge debugausgaben, damit ich seh, was in der variable drin steht... gdb hab ich noch nie wirklich verwendet...

    hth,
    ciao


  • Mod

    void ChangeInetnum(char *pTinetnum)                         //"-" rausnehmen und dafür Tab einsetzen
    {
        char *ptemp, *ptemp2;
       for(ptemp=pTinetnum;*ptemp!=' ';ptemp++){                                                  //Bis zur ersten Leerstelle springen
           ;
       }
       for(ptemp2=ptemp;((int)*ptemp2)<48||((int)*ptemp2)>57;ptemp2++){             //Ab Leerstelle bis zur ersten Zahl-
           ;                                                                         //mit casting (int) ermittelt
       }
       *ptemp++='\t';
       *ptemp='\t';                                                                 //2 Tab zwischen die IPs
       ptemp++;
       while(*ptemp2!='\n'){
           *ptemp=*ptemp2;
          ptemp++;
          ptemp2++;
       }
       *ptemp++='\n';                                                               //hinten NewLine
       *ptemp='\0';                                                                 //und Ende dran
    
    }
    

    der cast nach int ist ganz sicher falsch - es würde mich wundern, wenn das nicht zu einer speicherschutzverletzung führt. du willst nicht wissen, ob die vier byte, an der stelle ptemp2, als integer interpretiert, kleiner als 48 bzw. grösser als 57 sind, sondern ob das zeichen, auf das ptemp2 zeigt, eine ziffer ist.

    for( ptemp2 = ptemp; *ptemp2 < '0' || *ptemp2 > '9'; ++ptemp2 );
    

    wenn du dir die bisherige ausgabedatei ansiehst, stellst du sicher fest, dass die zweite ip fast immer dieselbe ist.
    ein anderes mögliches problem ist, dass das programm nicht fehlertolerant ist. falls also die eingabedatei aus irgendeinem grund an einer stelle falsch formatiert ist, könntest du leicht probleme bekommen.
    zum beispiel:

    void ChangeTchanged(char *pTchanged)                        //Alles hinter Leerzeichen abtrennen
    {
        char *ptemp;
       for(ptemp=pTchanged;*ptemp!=' ';ptemp++){
           ;
       }
       *ptemp++='\n';
       *ptemp='\0';
    }
    

    was machst du, wenn die zeile mal kein weiteres leerzeichen enthält...
    also besser hier mindestens noch sicher stellen, dass nicht über das zeilenende hinweg gelesen wird, was du für den fall, dass die zeile falsch ist machen willst, bleibt dir überlassen. am simpelsten wäre, gar nichts zu tun:

    void ChangeInetnum(char *pTinetnum)             //"-" rausnehmen und dafür Tab einsetzen
    {
    	char *ptemp, *ptemp2;
    	for( ptemp = pTinetnum; *ptemp && *ptemp != ' '; ++ptemp );	//Bis zur ersten Leerstelle springen
    	if( ! *ptemp ) return;	// bei Zeilenende nichts tun
    	for( ptemp2 = ptemp; *ptemp2 && ( *ptemp2 < '0' || *ptemp2 > '9' ); ++ptemp2 );	//Ab Leerstelle bis zur ersten Zahl
    	if( ! *ptemp2 ) return;
    	if( ptemp + 2 > ptemp2 ) return;
    	*ptemp++ = '\t';
    	*ptemp++ = '\t';                                                                 	//2 Tab zwischen die IPs
    	while( *ptemp++ = *ptemp2++ );
    }
    


  • Das ist doch mal eine Aussage danke dir dafür.
    Also das erste wird richtig interpretiert so wie ich das gemeint hatte.

    Es liegt wohl an der formatierung, der Fehler tritt immer an der gleichen
    stelle auf, und habe das unter bsp von dir eingefügt und fehler liegt an
    einer anderen stelle. so werde ich mal jeden fehler beseitigen.

    danke dir camper

    muss dazu sagen das mein ersten freies programm mehr oder weniger frei
    schnauze gemacht, jo einige sachen die man besser machen könnte


  • Mod

    logisch, muss funktionieren, du castest ja nach int NACHDEM du den zeiger dereferenziert hast - das ist lediglich überflüssig; hab ich geschlafen.
    ob den cast dort hast oder nicht ist völlig egal.
    kleiner tip: (läuft aber vermutlich unter schlechter stil 🙂 )

    wenn du schon castest, dann so dass es was bringt:

    for( ptemp2 = ptemp; *ptemp2 && (unsigned char)( *ptemp2 - '0' ) > 9; ++ptemp2 );    //Ab Leerstelle bis zur ersten Zahl
    


  • @pradox
    Versuch mal den Fehler etwas weiter einzugrenzen. Du kannst dir dazu z. B. einfach die Zeilennummer ausgeben lassen, bei der es kracht. Sollte es immer die selbe sein, dann versuch genau bei dieser Zeile zu debuggen.

    Michael E. schrieb:

    Lern debuggen 😡

    BTW: Dein RAM ist wahrscheinlich zu klein.

    Man kann nicht immer so einfach debuggen! Quäl du dich mal durch 14 MB durch mit dem Debugger. Da muss man den Fehler erstmal anders eingrenzen und dann kann man mit dem Debugger ran gehen. Außerdem hättest du das auch ein wenig höflicher formulieren können.


Anmelden zum Antworten