C Valgrind报告无效的写入错误

C Valgrind报告无效的写入错误,c,valgrind,C,Valgrind,这比我之前的Valgrind问题更加集中;在分析命令行选项时,我试图缩小写入和读取错误的范围: #include <stdio.h>

这比我之前的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");
}
当我使用
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()

第二个错误出现在
printUsage()
中的
fprintf
语句上

第46行为下一行:

 if (parseCommandLineInputs( &argc, &argv ) != 0)
 fprintf(stderr, "my usage statement\n\n");
第217行为下一行:

 if (parseCommandLineInputs( &argc, &argv ) != 0)
 fprintf(stderr, "my usage statement\n\n");

我的应用程序有什么问题,可以解释为什么会出现这些错误?

缺少太多内容,因此很难判断到底发生了什么。我想
pid
pid\t
? 我看到的唯一一件事是:

sprintf(uniqTag, "pid%d.%s", pid, uts.nodename);
pid\u t
不一定是
int
,因此
sprintf
在解析其参数和混乱堆栈时可能走错了方向。但是,
gcc
应该告诉您,如果您使用
-Wall
进行编译,我想是这样的


尝试使用不同的编译器编译,例如,

缺少太多内容,因此很难判断发生了什么。我想
pid
pid\t
? 我看到的唯一一件事是:

sprintf(uniqTag, "pid%d.%s", pid, uts.nodename);
pid\u t
不一定是
int
,因此
sprintf
在解析其参数和混乱堆栈时可能走错了方向。但是,
gcc
应该告诉您,如果您使用
-Wall
进行编译,我想是这样的


尝试使用不同的编译器进行编译,例如,

我会立即想到两件事:

  • *argv[1]与(*argv)[1]不同,这可能是您的意思。数组下标优先于指针解引用。这将导致指针无效。正如许多有经验的程序员告诉你的那样:“不要试图记住运算符的优先级——如果有疑问,请使用括号,如果不只是使用括号的话。”

  • -调试时,编译器标志中的O3是一个很大的禁忌。编译器会把你的代码弄得一团糟,使你的生活变得不可能。变量可以完全消失,函数可以在内联时神秘地消失。如果您的代码使用-O0编译、链接和运行(IIRC一些代码包含内联程序集需求-O1和一些(所有?)GCC版本),请使用它,否则最多使用-O1


我立刻想到两件事:

  • *argv[1]与(*argv)[1]不同,这可能是您的意思。数组下标优先于指针解引用。这将导致指针无效。正如许多有经验的程序员告诉你的那样:“不要试图记住运算符的优先级——如果有疑问,请使用括号,如果不只是使用括号的话。”

  • -调试时,编译器标志中的O3是一个很大的禁忌。编译器会把你的代码弄得一团糟,使你的生活变得不可能。变量可以完全消失,函数可以在内联时神秘地消失。如果您的代码使用-O0编译、链接和运行(IIRC一些代码包含内联程序集需求-O1和一些(所有?)GCC版本),请使用它,否则最多使用-O1


这不是完整的程序(没有
#包括
s,没有
uts
的定义,
uniqTag
pid
)。为什么
parseCommandLineInputs
中的行充满了尾随空间?您希望我们如何仅用一半的信息调试您的程序?uts在哪里,uniqTag?淀粉c的第46行和第217行是什么?您是否尝试过使用--db attach=yes?这不是完整的程序(否
#包括
s,没有定义
uts
uniqTag
,或
pid
)。为什么
parseCommandLineInputs
中的行充满了尾随空间?您希望我们如何仅用一半的信息调试您的程序?uts在哪里,uniqTag?淀粉c的第46行和第217行是什么?您是否尝试过使用--db attach=yes?谢谢您的帮助。我最终用
strdup
语句替换了
malloc/sprintf
语句。无论出于何种原因,这修复了valgrind错误消息。感谢您的帮助。我最终用
strdup
语句替换了
malloc/sprintf
语句。无论出于何种原因,这修复了valgrind错误消息。