2017-02-20 2 views
0

Ich versuche, eine Funktion zu tun, die einen bestimmten Code aus Kommentaren bereinigt. Der Code funktioniert gut, aber Valgrind mag es nicht. Die Eingabe enthält den Code, der bereinigt werden soll, und ich versuche, den bereinigten Code in newcode zu speichern. Ich habe verschiedene Werte mit Malloc ausprobiert, aber Valgrind scheint es nicht zu mögen. Mein Code sieht wie folgt aus:Probleme mit Valgrind

char *remove_comments(char *input) 
{ 
    int a=0; 
    char *newcode=malloc((strlen(input))*sizeof(char)); 
    int c=0; 
    while (a<strlen(input)){ 
     if((*(input+a)=='/') && (*(input+a+1) =='/')){ 
      while(*(input+a)!='\n'){ 
       a++; 
      } 
      a++; 
     } 
     if(*(input+a)=='/' && *(input+a+1)=='*'){ 
      int b=1; 
      while(b!=0){ 
       a++; 
       if(*(input+a)=='*' && *(input+a+1)=='/'){ 
        b--; 
       } 
      } 
      a++; 
      a++; 
     } 
     *(newcode+c)=*(input+a); 
     a++; 
     c++; 
    } 
    free(input); 
    return newcode; 
} 

und die valgrind Ausgabe sieht wie folgt aus:

==30337== Conditional jump or move depends on uninitialised value(s) 
==30337== at 0x402E50: mycompare_new (checkhelp.c:86) 
==30337== by 0x401F23: test_remove_comments (test_source.c:81) 
==30337== by 0x406FD2: srunner_run (in /tmp/user/ee67882dc0b6fb0b4d921c48de81577a5d87cccdc65e0a1580d6726d197a5e87/c-kurssi/Module_3/08_polisher/test/test) 
==30337== by 0x402512: tmc_run_tests (tmc-check.c:134) 
==30337== by 0x4021A7: main (test_source.c:206) 
==30337== Uninitialised value was created by a heap allocation 
==30337== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==30337== by 0x402FF1: remove_comments (source.c.nomain.c:18) 
==30337== by 0x401EBD: test_remove_comments (test_source.c:74) 
==30337== by 0x406FD2: srunner_run (in /tmp/user/ee67882dc0b6fb0b4d921c48de81577a5d87cccdc65e0a1580d6726d197a5e87/c-kurssi/Module_3/08_polisher/test/test) 
==30337== by 0x402512: tmc_run_tests (tmc-check.c:134) 
==30337== by 0x4021A7: main (test_source.c:206) 
==30337== 
==30337== Conditional jump or move depends on uninitialised value(s) 
==30337== at 0x402E50: mycompare_new (checkhelp.c:86) 
==30337== by 0x4020BA: test_remove_comments (test_source.c:109) 
==30337== by 0x406FD2: srunner_run (in /tmp/user/ee67882dc0b6fb0b4d921c48de81577a5d87cccdc65e0a1580d6726d197a5e87/c-kurssi/Module_3/08_polisher/test/test) 
==30337== by 0x402512: tmc_run_tests (tmc-check.c:134) 
==30337== by 0x4021A7: main (test_source.c:206) 
==30337== Uninitialised value was created by a heap allocation 
==30337== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==30337== by 0x402FF1: remove_comments (source.c.nomain.c:18) 
==30337== by 0x402045: test_remove_comments (test_source.c:102) 
==30337== by 0x406FD2: srunner_run (in /tmp/user/ee67882dc0b6fb0b4d921c48de81577a5d87cccdc65e0a1580d6726d197a5e87/c-kurssi/Module_3/08_polisher/test/test) 
==30337== by 0x402512: tmc_run_tests (tmc-check.c:134) 
==30337== by 0x4021A7: main (test_source.c:206) 
==30337== 
+3

Ich denke, Sie fehlen die Null-Terminierung Char (+1) zu Ihrem 'malloc' –

+1

Valgrind beschwert sich auf Ihre Tests, was macht mycompare_new? –

+0

Sie könnten a, b und c etwas beschreibenderes wie 'input_pos',' output_pos' nennen (sie können durch Inkrementieren der Zeiger selbst beseitigt werden, behalten Sie einfach eine Kopie von 'newcode', um zurückzukehren). Ich denke "b" kann durch ['while (1)' und 'break'] ersetzt werden (https://www.tutorialspoint.com/cprogramming/c_break_statement.htm). Sie können zweimal mit "a + = 2" erhöhen. Es ist eine schlechte Idee, den Speicher anderer Leute zu befreien, es sei denn, es handelt sich um einen Destruktor, gib keine "Eingabe" frei. Lassen Sie den Anrufer entscheiden, wann er damit fertig ist. – Schwern

Antwort

2

Es Haufen Probleme mit diesem Code sind.

  1. Sie arbeiten mit C-Strings, die Sequenzen von Zeichen mit einem Terminal NUL (\ 0) sind. Wenn Sie jedoch Platz für neuen Code reservieren, ordnen Sie nur die Länge der Eingabe zu und lassen keinen Platz für die NUL. Sie sollten strlen(input)+1 zuweisen.

  2. Die Schleife vergleicht a mit strlen(input) jedes Mal durch die Schleife, was bedeutet, dass Sie die Länge der Eingabe für jedes Zeichen, das Sie sehen, neu berechnen. Berechne es einmal und speichere es in einer Variablen oder nur in der Schleife while (!input[a]), was dazu führt, dass es aufhört zu loopen, wenn es am Ende der Eingabe auf NUL trifft.

  3. Die *(input+a) Syntax ist nicht notwendig; Verwenden Sie input[a].

  4. Wenn die letzten zwei Bytes der Zeichenfolge "//" sind oder wenn der Code ein "//" gefolgt von "\ n" enthält, wird die innere while-Schleife durch den Speicher durchlaufen, bis sie gefunden wird ein'. Überprüfen Sie immer auf NUL, wenn Sie über Strings loopen und beenden Sie den Loop, wenn Sie einen finden. Das Gleiche gilt für die innere Schleife für den Fall "/ * ... * /".

  5. Der Code wird "/ * /" fälschlicherweise als Kommentar erkennen.

  6. Wenn die Eingabe zwei Kommentare in einer Zeile enthält, z. B. "/ * X * // * Y * /", erkennt der Code den zweiten Kommentar nicht. Es wird den ersten Kommentar überspringen, aber dann das neue '/' des zweiten Kommentars zu newcode hinzufügen und fortfahren.

  7. Sie fügen am Ende von newcode kein NUL hinzu, bevor Sie es zurückgeben.

Ich stelle mir vor, Sie bekommen die valgrind Fehler im Test, weil Sie strcmp mit dem zurückgegebenen String tun, und da es nicht NUL-terminiert, strcmp wandert ab in uninitialized Heap-Speicher.