Valgrind说-大小为8的无效写入

时间:2019-04-20 16:16:02

标签: c linux valgrind


通过valgrind运行程序时遇到错误,我已经在其他任何与此主题有关的帖子中寻找解决方案。
我的程序假设模拟一个Linux终端,当我尝试运行一个简单的命令,例如“ echo hello world”时,我得到以下信息:

==21569== Invalid write of size 8
==21569==    at 0x108FDF: getInput (in /home/sahar/Desktop/ex1/ex1)
==21569==    by 0x108B95: main (in /home/sahar/Desktop/ex1/ex1)
==21569==  Address 0x52324c0 is 0 bytes after a block of size 32 alloc'd
==21569==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21569==    by 0x108D2F: getInput (in /home/sahar/Desktop/ex1/ex1)
==21569==    by 0x108B95: main (in /home/sahar/Desktop/ex1/ex1)
==21569== 
==21570== Syscall param execve(argv) points to uninitialised byte(s)
==21570==    at 0x4F20E37: execve (syscall-template.S:78)
==21570==    by 0x4F21732: execvpe (execvpe.c:138)
==21570==    by 0x109053: execute (in /home/sahar/Desktop/ex1/ex1)
==21570==    by 0x108BA5: main (in /home/sahar/Desktop/ex1/ex1)
==21570==  Address 0x52324b8 is 24 bytes inside a block of size 32 alloc'd
==21570==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21570==    by 0x108D2F: getInput (in /home/sahar/Desktop/ex1/ex1)
==21570==    by 0x108B95: main (in /home/sahar/Desktop/ex1/ex1)
==21570== 
hello world

我的代码:


#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <pwd.h>

#define MAXCOM 510 // max number of letters in a command  

void printDirectory();
char** getInput();
int countWords(char *str);
void execute(char** command);
void freeCommand(char ** cmd);

int countCmd=0, cmdLength=0;        //global

int main()
{
    while(1)
    {
        printDirectory(); 
        char** command = getInput();
        execute(command);
        freeCommand(command);
    }
}

//Function to print the current directory
void printDirectory() 
{ 
    char cwd[200];
    getcwd(cwd, sizeof(cwd)); 
    struct passwd *pw = getpwuid(getuid());
    const char *username = pw->pw_name;
    printf("%s@%s>", username,cwd);
} 

//Function to get input from the user 
char** getInput() 
{ 
    char command[MAXCOM];
    char *word; 
    char **cmdArr;
    char done[]="done", cd[]="cd";              //specific cases

    if(fgets(command,MAXCOM,stdin)==NULL)
        strcpy(command," ");                    //empty string

    cmdLength=cmdLength+strlen(command);

    char *pos;
    if ((pos=strchr(command, '\n')) != NULL)    //deleting \n
        *pos = '\0';                        

    int numOfWords = countWords(command);
    countCmd++;

    cmdArr = malloc((numOfWords+1) * sizeof(char*));
    if(cmdArr == NULL)
    {
        printf("ERR");
        freeCommand(cmdArr);
        exit(1);
    }

    //dealing with the first word at the string
    word = strtok(command, " ");
    cmdArr[0] = malloc((strlen(word)+1) * sizeof(char));
    if(cmdArr[0] == NULL)
    {
        printf("ERR");
        freeCommand(cmdArr);
        exit(1);
    }
    strcpy(cmdArr[0], word);

    //checking if done
    if(strcmp(done,cmdArr[0]) == 0)
    {
        printf("Num of commands: %d\n",countCmd);
        printf("Total length of all commands: %d\n",cmdLength);
        printf("Average length of all commands: %f\n",(double)((double)cmdLength/(double)countCmd));
        printf("See you Next time !\n");
        exit(0);
    }

    //cd command undefined yet
    if(strcmp(cd, cmdArr[0]) == 0)
    {
        printf("Comand not supperted (Yet)\n");
        main();
    }

    //dealing with the rest of the string
    for(int i=1 ; i<numOfWords ; i++)
    {
        word = strtok(NULL, " ");
        cmdArr[i] = malloc((strlen(word)+1) * sizeof(char));
        if(cmdArr[i] == NULL)
        {
            printf("ERR");
            freeCommand(cmdArr);
            exit(1);
        }
        strcpy(cmdArr[i],word);
    }
    cmdArr[numOfWords+1]=(char *) NULL;          //last value is NULL
    return cmdArr;
} 

void execute(char** command) 
{ 
    // Forking a child 
    pid_t pid = fork();  
    if (pid == -1) { 
        printf("ERR");
        return; 
    } 
    else if (pid == 0) { 
        if (execvp(command[0], command) < 0) { 
            //printf("Could not execute command...\n"); 
            exit(0);
        } 
        exit(0); 
    } else { 
        // waiting for child to finish 
        wait(NULL);  
        return; 
    } 
} 

int countWords(char *str) 
{ 
    int state = 0; 
    int words = 0;  //word count 

    while (*str) 
    { 
        //if next character is a separator, changeing the state to OUT 
        if (*str == ' ' || *str == '\n' || *str == '\t') 
            state = 0; 

        //if next character is not a separator and state is OUT- set the state to IN and increment word count 
        else if (state == 0) 
        { 
            state = 1; 
            ++words; 
        } 

        //next character 
        ++str; 
    } 
    return words; 
} 

void freeCommand(char ** cmd)
{
    int i=0;
    if(cmd!=NULL && getpid==0) //only child can free the allocated memory
    {
        while(cmd[i]!=NULL){
            free(cmd[i]);
            i++;
        }
    }
    free(cmd);
}

我已经检查了我的malloc函数很多次了,无法弄清楚问题出在哪里...知道吗?谢谢。

1 个答案:

答案 0 :(得分:1)

我认为您的问题在这里:

cmdArr = malloc((numOfWords+1) * sizeof(char*));
...
cmdArr[numOfWords+1]=(char *) NULL;          //last value is NULL

您需要

cmdArr[numOfWords]=(char *) NULL;