(sysmalloc: Assertion) 使用多个 MALLOCS 来填充 HEAP 中的三重指针

问题描述 投票:0回答:1

我是编程新手,作为一项任务,我被告知要做一个迷你 Bash。我决定做一个解析器,以防要分析的命令中没有词法错误,将填充一个 char*** (据我所知它将是一个字符串矩阵)。

我遇到的问题是,在某个时候我得到了一个我不理解的 sysmalloc 断言。我的代码非常糟糕(直到现在我从来没有做过免费的),但我认为它至少应该运行并使用 valgrind 告诉我我有内存泄漏。

我开始学习如何正确使用 C 指针,所以请多关照。如果有人知道问题出在哪里(它必须在解析器函数中),我将非常感谢他们向我解释。这是代码(如果有人需要查看更多代码,请告诉我):

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>                    
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <unistd.h>
#include <stdbool.h>

char*** parser(char*);
size_t token_counter(const char const *, char);
bool double_occurrence(char*, char, size_t);
bool line_semantic_correctness(char*);
bool arg_semantic_correctness(char*, int);

int main(int argc, char *argv[]){
    char a[]={"cat /etc/passwd | grep -i \"boo\" | grep bash suca blyat andrea e frocio | a b c d e f g h i j k l m n o p q r s t u v w x y z | <file1 <file2 suca"};
    char*** to_parse = parser(a);
    int cmd_index = 0;

    if(to_parse != NULL){
        while(to_parse[cmd_index] != NULL){
            int arg_index = 0;
            printf("cmd %d\n", cmd_index);
            while(to_parse[cmd_index][arg_index] != NULL){
                printf("%s\n", to_parse[cmd_index][arg_index]);
                ++arg_index;
            }
            ++cmd_index;
        }
    }
}

char*** parser(char* line){
    if(!line_semantic_correctness(line))
        return NULL;

    char*** mtrx = NULL;

    size_t cmds_num = token_counter(line, '|');         //counts how many non '|' tokens are present in the command
    size_t rowsto_alloc = cmds_num+1;
    if((mtrx=malloc(rowsto_alloc*sizeof(char**))) == NULL){        
        perror("");
        return NULL;
    }
    mtrx[cmds_num]=NULL;
    char* cmd;
    char* cmd_context;
    int cmd_index = 0;
    for(cmd=strtok_r(line, "|", &cmd_context); cmd!=NULL; 
        cmd=strtok_r(NULL, "|", &cmd_context)){
        size_t args_num = token_counter(cmd, ' ');                                                  
        //counts how many non ' ' tokens are present in the command
        size_t colsto_alloc = args_num+1;                                                                      
        if((mtrx[cmd_index]=malloc(colsto_alloc*sizeof(char*))) == NULL){
            perror("");
            //free?
            return NULL;
        }
        mtrx[cmd_index][cmds_num] = NULL;
        char** toredirect = NULL;
        size_t toredirect_sz = 1;
        char* arg;
        char* arg_context;
        int arg_index = 0;
        for(arg=strtok_r(cmd, " ", &arg_context); arg!=NULL; arg=strtok_r(NULL, " ", &arg_context)){
            if(!arg_semantic_correctness(arg, arg_index)){                                                      //analyzes a particular command and returns false when it's not a valid
                perror("");
                //MEGA FREE: da implementare
                return NULL;
            }
            size_t arg_sz = strlen(arg) + 1;
            //if in a command I have redirections written like "<file1" or ">file2" I save them in a double pointer and after analyzing the particular command I push them at the end 
            //of the corresponding row in my triple pointer
            if((arg[0] == '<' ) || (arg[0] == '>' )){
                size_t torealloc = toredirect_sz + 1;
                if((toredirect=realloc(toredirect, torealloc*sizeof(char*))) == NULL){
                    perror("");
                    //free da fare
                    return NULL;
                }
                toredirect[toredirect_sz] = NULL;

                if((toredirect[toredirect_sz-1] = malloc(arg_sz)) == NULL){
                    perror("");
                    //free da fare
                    return NULL;                                        
                }
                strncpy(toredirect[toredirect_sz-1], arg, arg_sz);
                ++toredirect_sz;
            }
            //in the case the particular argument of a command is not a redirection, I put it directly on the triple pointer
            else{
                //AFTER THIS ALLOCATION I GET THE SYSMALLOC ASSERTION (when trying to add the second command to the triple pointer)
                if((mtrx[cmd_index][arg_index] = malloc(arg_sz)) == NULL){
                    perror("");
                    //mega free!!!
                    return NULL;
                }
                strncpy(mtrx[cmd_index][arg_index], arg, arg_sz);
                ++arg_index;
            }
        }
        for(int i = 0; arg_index+i < args_num; ++i){
            size_t tocopy_sz = strlen(toredirect[i]) + 1;
            if((mtrx[cmd_index][arg_index+i] = malloc(tocopy_sz*sizeof(char))) == NULL){
                perror("");
                //mega free!!!
                return NULL;
            }
            strncpy(mtrx[cmd_index][arg_index+i], toredirect[i], tocopy_sz);
        }
        //FREE DI REDIRECTIONS !!!!!!!
        ++cmd_index;
    }
    return mtrx;
 }

size_t token_counter(const char const * str, char delim){
    size_t tok_num = 0;
    size_t str_sz = strlen(str);
    bool increment = true;
    for(int i = 0; i < str_sz; ++i){
        if(str[i] == delim){
            increment = true;
            continue;
        }
        else if(increment == true){
            ++tok_num;
            increment = false;
        }
    }
    return tok_num;
}

bool double_occurrence(char* str, char occ, size_t line_sz){
    for(int i = 0; i < (line_sz - 1); ++i){
        if((str[i] == occ) && (str[i+1] == occ))
            return true;
    }
    return false;
}

bool line_semantic_correctness(char* line){
    if(line == NULL){
        perror("");
        return false;
    }
    if(line[0] == '\0'){
        perror("");
        return false;
    }

    size_t line_size = strlen(line);

    if(double_occurrence(line, '|', line_size)){
        perror("");
        return false;
    }

    if((line[0] == '|') || (line[line_size - 1] == '|')){
        perror("");
        return false;
    }

    return true;
}

// se restituisce false, RICORDIAMOCI di fare la mega FREE
bool arg_semantic_correctness(char* arg, int arg_index){
    switch(arg_index){
        case 0:
            if(arg[0] == '\0'){
                perror("");
                return false;
            }
        default:
            //controllo redirezioni senza file attaccati 

            if(strlen(arg) == 1){
                if((arg[0] == '<') || (arg[0] == '>')){
                    perror("");
                    return false;
                }
            }
    }
    return true;
}
c parsing pointers malloc overflow
1个回答
0
投票
99                      if((mtrx[cmd_index][arg_index] = malloc(arg_sz)) == NULL){
(gdb) p cmd_index 
$10 = 0
(gdb) p arg_index
$11 = 1
(gdb) n
104                     strncpy(mtrx[cmd_index][arg_index], arg, arg_sz);
(gdb) c
Continuing.

Breakpoint 2, parser (line=0x7fffffffdfc0 "cat") at main.c:99
99                      if((mtrx[cmd_index][arg_index] = malloc(arg_sz)) == NULL){
(gdb) p cmd_index 
$12 = 1
(gdb) p arg_index
$13 = 0
(gdb) p arg_sz
$14 = 5
(gdb) n

也许错误是你不能将 char*** 与数组一起使用,因为系统不知道 array[] 或 array[][] 或 array[][][] 中的大小

就像 int** in array[12] 和 array[3][4] 是不同的

你需要用 char[][][] 初始化这个 char***

char a[]={"cat /etc/passwd | grep -i \"boo\" | grep bash andrea e | a b c d e f g h i j k l m n o p q r s t u v w x y z | <file1 <file2 suca"};

char* argv 中的这个不是 char 数组,它是字符串数组,就像

argv[0] = ".\a.out"
argv[1] = "cat"
argv[2] = "/etc/passwd"
......
© www.soinside.com 2019 - 2024. All rights reserved.