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 allesES 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 mehrinetnum: 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
-
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
-
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.