Valgrind сообщает об ошибках записи - PullRequest
0 голосов
/ 18 ноября 2010

Это более сфокусировано, чем мой предыдущий вопрос о Вальгринде; Я пытаюсь сузить ошибки записи и чтения при разборе параметров командной строки:

#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");
}

Мой make-файл выглядит так:

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");

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

Ответы [ 2 ]

4 голосов
/ 19 ноября 2010

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

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

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

0 голосов
/ 18 ноября 2010

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

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

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

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

...