2010-11-18 7 views
0

이것은 이전의 Valgrind 질문보다 중점을 두었습니다.잘못된 쓰기 오류를보고하는 Valgrind

#include <stdio.h>                                                      
#include <stdlib.h>                                                     
#include <unistd.h>                                                     
#include <sys/utsname.h>                                                    
#include <sys/stat.h>                                                     
#include <string.h>                                                     
#include <locale.h>                                                     
#include <bzlib.h>                                                      
#include <zlib.h>                                                      
#include "starch.h" 

#define BUFMAXLEN 1024 

int main(int argc, char **argv) { 
    if (parseCommandLineInputs(&argc, &argv) != 0) 
     exit(EXIT_FAILURE); 

    return 0; 
} 

int parseCommandLineInputs(int *argc, char ***argv) { 

    pid_t pid;                                                       
    struct utsname uts; 
    char uniqTag[BUFMAXLEN]; 

    if ((*argc == 1) || (*argc > 4)) {                                                 
     printUsage(); 
     return -1;                                                   
    }                                                         

    if ((pid = getpid()) < 0) {                                                  
     fprintf(stderr, "\n\t[starch] - Error: Could not obtain process ID\n\n");                                      
     return -1;                                                   
    }                                                         
    uname(&uts);                                                      
    sprintf(uniqTag, "pid%d.%s", pid, uts.nodename);                                             

    switch (*argc) {                                                     
     case 2: {                                                      
      if (strcmp(*argv[1], "-") != 0) {                                               
       if (fileExists(*argv[1]) != 0) { /* standard input */                                        
        ... 
    } 

    return 0; 
} 


int fileExists(char *fn) { 
    struct stat buf; 
    int i = stat (fn, &buf); 
    if (i == 0) 
     return 0; 
    return -1; 
} 

void printUsage() { 
    fprintf(stderr, "my usage statement\n\n"); 
} 

내 메이크 파일은 다음과 같다 : 나는 명령 줄 옵션 구문 분석 할 때 쓰기를 좁혀 오류를 읽으려고하고

CC  = gcc                                                       
CFLAGS = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1 -DUSE_ZLIB -O3 -Wformat -Wall -pedantic -std=gnu99 -g                               
BIN  = ../bin                                                      

all: starch                                                       
    rm -rf *~                                                       

starch: starch.o                                                      
    mkdir -p $(BIN) && $(CC) ${CFLAGS} starch.o -lbz2 -lz -o ${BIN}/starch                                        
    rm -rf *~                                                       

clean: 
    rm -rf *.o *~ ${BIN}/starch 

을 내가 valgrind 실행할 때 다음과 같은 오류를 얻을 :

$ valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes -v ../bin/starch 

... 

==2675== 1 errors in context 1 of 2:                                                 
==2675== Invalid read of size 8                                                  
==2675== at 0x3AB4262243: fwrite (in /lib64/libc-2.5.so)                                           
==2675== Address 0x7fedffd68 is on thread 1's stack                                             
==2675==                                                        
==2675==                                                        
==2675== 1 errors in context 2 of 2:                                                 
==2675== Invalid write of size 8                                                  
==2675== at 0x401AA6: parseCommandLineInputs (starch.c:217)                                           
==2675== by 0x7FF0000AF: ???                                                  
==2675== by 0x401DFA: main (starch.c:46)                                               
==2675== Address 0x7fedffd68 is on thread 1's stack 

어디서나 fwrite()을 사용하지 않으므로 처음 사용할 때 아무 것도 알려주지 못합니다.

fprintf 문에서 printUsage()의 두 번째 오류가 발생합니다.

fprintf(stderr, "my usage statement\n\n"); 

이러한 오류가 표시되는 이유를 설명 내 응용 프로그램에 어떤 문제가 :

if (parseCommandLineInputs(&argc, &argv) != 0) 

라인 (217)이 다음 줄은 다음과 같습니다

선 (46)는 다음 줄입니까?

+1

이 전체 프로그램 (NO'#의 include's,'uts','uniqTag', 또는'pid'에 대한 어떤 정의가) 없습니다. 'parseCommandLineInputs'의 행이 뒤 공백으로 가득 찬 이유는 무엇입니까? – pmg

+0

정보의 절반만으로 어떻게 프로그램을 디버깅 할 수있을 것으로 기대하십니까? uts, uniqTag는 어디에 있습니까? starch.c의 46과 217 행은 무엇입니까? --db-attach = yes를 사용해 보셨습니까? – BatchyX

답변

4

두 가지 :

  • * 변수는 argv [1]과 동일하지 않습니다 (* 변수는 argv) [1] 당신은 아마 무슨 뜻이다. 배열 첨자는 포인터 역 참조보다 우선합니다. 이로 인해 잘못된 포인터가 생성됩니다. 경험 많은 프로그래머가 다음과 같이 말할 것입니다. "연산자의 우선 순위를 기억하려고하지 마십시오. 의심스러운 경우 괄호를 사용하십시오.

  • 컴파일러 플래그의 -O3은 디버깅 할 때 큰 NO NO입니다. 컴파일러가 코드를 너무 복잡하게하여 사용자의 삶을 불가능하게 만듭니다. 변수는 완전히 사라질 수 있고 함수는 인라인 될 때 ​​신비하게 멀리 갈 수 있습니다. 코드가 컴파일되면 -O0으로 링크하고 실행합니다 (IIRC 인라인 어셈블리가 포함 된 일부 코드에는 -O1과 일부 GCC 버전 모두 필요). 그렇지 않으면 -O1을 사용하십시오.

+0

도움 주셔서 감사합니다.필자는'malloc/sprintf' 문을'strdup' 문으로 대체했습니다. 어떤 이유로 든 valgrind 오류 메시지가 수정되었습니다. –

0

누락 된 항목이 너무 많아서 무슨 일이 일어나고 있는지 쉽게 알 수 없습니다. pidpid_t이라고 생각하십니까? 그때 볼 있는 유일한 방법은 이것이다 :

sprintf(uniqTag, "pid%d.%s", pid, uts.nodename); 

pid_t는 반드시 int 그렇게 sprintf이 인수를 구문 분석 할 때 잘못된 궤도에하고 당신의 스택을 messup 수 없습니다. 그러나 gcc-Wall으로 컴파일하면 알려줬어야합니다.

다른 컴파일러로 컴파일 해 봅니다 (예 : clang). 바로 나에게 팝업

관련 문제