2017-02-20 29 views
0

我正在嘗試做一個清理給定代碼的函數。代碼工作正常,但valgrind不喜歡它。輸入包含應該清理的代碼,並且我試圖將清理後的代碼保存到新代碼中。我用malloc嘗試了不同的值,但valgrind似乎不喜歡它。我的代碼如下所示: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; 
} 

和Valgrind的輸出是這樣的:

==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

我想你錯過了你的'malloc'的空終止字符(+1) –

+1

Valgrind抱怨你的測試,mycompare_new做了什麼? –

+0

您可能想要命名a,b和c這些更具描述性的內容,如'input_pos','output_pos'(它們可以通過增加指針本身來完成,只需保留'newcode'的副本返回)。我認爲'b'可以用['while(1)'和'break'](https://www.tutorialspoint.com/cprogramming/c_break_statement.htm)代替。你可以用'a + = 2'增加兩次。釋放其他人的記憶是一個壞主意,除非它是一個析構函數,不要釋放「輸入」。讓來電者決定何時完成。 – Schwern

回答

2

有一堆與此代碼的問題。

  1. 您正在處理C字符串,它是帶有終端NUL(\ 0)的字符序列。但是當你爲newcode分配空間時,你只分配輸入的長度並且不留給NUL空間。您應該分配strlen(input)+1

  2. 循環每次通過循環比較astrlen(input),這意味着您將重新計算您看到的每個字符的輸入長度。計算一次並將其保存在一個變量中,或者只循環while (!input[a]),這將導致它在輸入結束時遇到NUL時停止循環。

  3. *(input+a)語法是不必要的;使用input[a]

  4. 如果字符串的最後兩個字節是「//」,或者如果代碼包含「//」後面跟着「\ n」,那麼inner while循環將遍歷內存,直到遇到'\ n'。在循環字符串時總是檢查NUL,並在遇到循環時終止循環。與「/ * ... * /」情況下的內部循環相同。

  5. 代碼會錯誤地將「/ * /」識別爲註釋。

  6. 如果輸入在一行中包含兩個註釋,例如「/ * X * // * Y * /」,那麼代碼將無法識別第二個註釋。它會跳過第一條評論,然後將第二條評論的首字母'/'添加到新代碼並繼續。

  7. 在返回之前,您並未在newcode的末尾添加NUL。

我想你得到的valgrind錯誤的測試,因爲你正在做的strcmp與返回的字符串,因爲它不是NULL結尾,STRCMP恍惚斷成未初始化的堆內存。