2010-11-18 3 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"); 
} 

Мой Makefile выглядит следующим образом:

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().

Линия 46 является следующая строка:

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

Линия 217 является следующая строка:

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

Что случилось с моим заявлением, что объясняет, почему появляются эти ошибки?

+1

Это не полная программа (нет '# include', нет определения для 'uts',' uniqTag' или 'pid'). Почему строки в 'parseCommandLineInputs' заполнены конечным пространством? – pmg

+0

Как вы ожидаете от нас отладки вашей программы только с половиной информации? где uts, uniqTag? какова линия 46 и 217 крахмала.c? вы пробовали использовать --db-attach = да? – BatchyX

ответ

4

Две вещи, которые всплывают мне сразу:

  • * ARGV [1] не то же самое, как (* ARGV) [1], которая является то, что вы, вероятно, имеете в виду. Подписи на основе массива имеют приоритет над разыменованием указателя. Это приводит к недопустимому указателю. Как многие опытные программисты скажут вам: «Не пытайтесь вспомнить приоритет операторов - если сомневаетесь, используйте круглые скобки, если не используете их в любом случае».

  • -O3 в флагах компилятора является большим жирным NO-NO при отладке. Компилятор будет калечить ваш код настолько, что он может сделать вашу жизнь невозможной. Переменные могут полностью исчезнуть, и функции могут загадочно исчезнуть, когда они вступят в силу. Если ваш код компилируется, ссылки и запускаются с -O0 (код IIRC, содержащий встроенную сборку, -O1 с некоторыми (все?) Версиями GCC), используйте его, иначе используйте -O1 максимум.

+0

Спасибо за помощь.Я закончил замену операторов 'malloc/sprintf' операторами' strdup'. По какой-то причине это фиксировало сообщения об ошибках valgrind. –

0

Слишком много недостатков, поэтому не легко сказать, что происходит. Я полагаю, что pid - pid_t? Единственное, что я тогда вижу это:

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

pid_t не обязательно int так sprintf может быть на ложном пути при анализе его аргументы и messup ваш стек. Но gcc должен был сказать вам, если вы скомпилируете -Wall, что, я полагаю.

Попробуйте выполнить компиляцию с помощью другого компилятора, например clang.

Смежные вопросы