2017-04-18 4 views
0

Ich habe einen C-Code geschrieben, um aus einer Eingabedatei zu lesen und in eine Ausgabedatei zu schreiben.Lesen und Schreiben in eine Datei mit Zeiger in C?

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/stat.h> 




int callreadwrite(char *infile, char *outfile) { 

    FILE *fi, *fo; 
    char *line = NULL, *line1 = NULL, *line2 = NULL, *line3 = NULL, *line4 = NULL, *line5 = NULL, *line6 = NULL,*baseline1 = "Count"; 

    size_t len = 0; 
    ssize_t read; 
    int i = 0, countt, klent, tlenn, neq_vctr = 0, n = 0, res = 0, fin = 0, Nlenn, c; 

    unsigned char *count, *klen, *tlen, *key, *msg, *nmac; 

    time_t ltime; // calendar time 
    ltime = time(NULL); // get current cal time 

    fi = fopen(infile, "r"); 
    fo = fopen(outfile, "w"); 



    while ((read = getline(&line1, &len, fi)) != -1) { 

     if (strncmp(baseline1, line1, 5) == 0) { 
     getline(&line2, &len, fi); 
     getline(&line3, &len, fi); 
     getline(&line4, &len, fi); 
     getline(&line5, &len, fi); 
     getline(&line6, &len, fi); 

     count = line1 + 8; 
     klen = line2 + 7; 
     tlen = line3 + 7; 
     key = line4 + 6; 
     msg = line5 + 6; 
     nmac = line6 + 6; 
     // convert string to integer: count, key length, message length, tag length 
     countt = strtol(count, NULL, 0); 
     fprintf(fo, "Count = %d\n", countt); 


     klent = strtol(klen, NULL, 0); 
     fprintf(fo, "Klen = %d\n", klent); 

     tlenn = strtol(tlen, NULL, 0); 

     fprintf(fo, "Count = %d\n", countt); 
     fprintf(fo, "Klen = %d\n", klent); 
     fprintf(fo, "Tlen = %d\n", tlenn); 
     fprintf(fo, "Key = %s", key); 
     fprintf(fo, "Msg = %s", msg); 
     fprintf(fo, "Nmac = %s", nmac); 




    } 

} 

fclose(fi); 
fclose(fo); 

return 0; 

} 




int main() { 
    callreadwrite("read.txt", "write.txt"); 

} 

Das Programm kopiert den Inhalt der Eingabedatei file.If den Inhalt der Eingabedateien ausgegeben werden als

Count = 0 
Klen = 10 
Tlen = 10 
Key = 82f3b69a1bff4de15c33 
Msg = fcd6d98bef45ed6850806e96f255fa0c8114b72873abe8f43c10bea7c1df706f10458e6d4e1c9201f057b8492fa10fe4b541d0fc9d41ef839acff1bc76e3fdfebf2235b5bd0347a9a6303e83152f9f8db941b1b94a8a1ce5c273b55dc94d99a171377969234134e7dad1ab4c8e46d18df4dc016764cf95a11ac4b491a2646be1 
Mac = 1ba0e66cf72efc349207 

Count = 1 
Klen = 10 
Tlen = 10 
Key = 4766e6fe5dffc98a5c50 
Msg = d68b828a153f5198c005ee36c0af2ff92e84907517f01d9b7c7993469df5c21078fa356a8c9715ece2414be94e10e547f32cbb8d0582523ed3bb0066046e51722094aa44533d2c876e82db402fbb00a6c2f2cc3487973dfc1674463e81e42a39d9402941f39b5e126bafe864ea1648c0a5be0a912697a87e4f8eabf79cbf130e 
Mac = 007e4504041a12f9e345 

folgt aber, wenn die Eingabedatei einen Eintrag mehr enthält seine Fehler gibt

Count = 3 
Klen = 142 
Tlen = 64 
Key = f78343071f61ee7d9f791bd53132e6d557928bcfe4b214bebf6f3592e46374c7ab148c3c4d6a1443a4675cf4321298c865b440631947b6b05f2c2a337d1cbb9b3661de974b4604eb41cc77c3659e85470e47e16f22a34619db935d59cbf5e1101ed401c020db069eff1035e9d1bff77bd8b3379e05ac0c20bc0e98aad7d7304dedd3bc5ed4136184649b5e0f7e5b 
Msg = d63b50b54e1536e35d5f3c6e29f1e49a78ca43fa22b31232c71f0300bd56517e4cd29ba11ee9f206f1ad31ee8f118c87004d6c6dfe837b70a9a2fa987c8b5b6680720c5dbf8791c1fcd6d59fa16cc20df9bc0fb39f41598a376476e45b9f06add8e34af01b373a9ce6a3d189484cacb6cbe0d3d5ef34d709d72c1dee43dc79da 
Mac = 086f674d778db491e73b6fbc5126233c6b6e1f066963356d49ea386d9c0868ad25bf6edad0371cde87cea94a18c6dba47535dfce2e40d2246ab17980495d656c 

das ist der Fehler als

*** Error in `./aout': munmap_chunk(): invalid pointer: 0x0000000000b70810 *** 
    ======= Backtrace: ========= 
    /lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f23e8d397e5] 


    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 
    Aborted (core dumped) 
folgt

Kann mir jemand sagen, wie man die Zeigerkarte beim Lesen den richtigen Ort zu machen.

+0

Sie sollten den Code Zeile für Zeile in einem Debugger durchlaufen, damit Sie den Ort des Absturzes eingrenzen können. –

+0

Warum ist es wichtig, "record by record" zu kopieren, warum nicht einfach alle Zeilen kopieren? Dieser Weg ist brüchiger, wenn z.B. In der Datei fehlt eine Zeile oder etwas. – unwind

+0

Hat Ihr Compiler keine Warnungen ausgegeben? – datell

Antwort

2

Das Problem liegt in Ihrer Handhabung der getline() Funktion. Es wird Speicher zuordnen für Sie, aber nur unter bestimmten Bedingungen:

  • lineptr == NULL und Len == 0: den Speicher zuteilen
  • len benötigt = 0: Raum neu zuweisen, wenn nicht groß genug

In Ihrem Fall initialisieren Sie die Zeilenzeiger, aber Sie verwenden die gleiche len-Variable für alle Lesevorgänge. Die getline() Funktion verwendet diese len, um zu verfolgen, wie viel Speicherplatz sie zugewiesen hat, so dass es eine len für jede der Zeilen benötigt.

Die einfachste Lösung besteht darin, für jede Zeile eine separate len-Variable zu erstellen.

size_t len1 = 0, len2 = 0, len3 = 0, len4 = 0, len5 = 0, len6 = 0; 

while ((read = getline(&line1, &len1, fi)) != -1) { 
    if (strncmp(baseline1, line1, 5) == 0) { 
    getline(&line2, &len2, fi); 
    getline(&line3, &len3, fi); 
    getline(&line4, &len4, fi); 
    getline(&line5, &len5, fi); 
    getline(&line6, &len6, fi); 
3

Ihr Hauptproblem ist mit getline. getline wird einen Puffer zuweisen und neu zuweisen. Sie geben einen Zeiger für jede Zeile, aber Sie verwenden eine einzelne len Variable.

Bei folgenden Aufrufen wird len als die Länge des aktuellen Puffers interpretiert, aber das ist nicht so. Folglich kann ein len, der größer als der aktuelle Puffer ist, mit einer Zeile, die zu diesem Puffer gemäß len passen würde, Speicher überschreiben, was zu undefiniertem Verhalten führt.

Verwandte Themen