Недопустимая запись размера 8 при переносе массива строк

#c #string #shell #valgrind #strtok

#c #строка #оболочка #valgrind #strtok

Вопрос:

Я пытаюсь написать свою собственную оболочку на C. У меня проблема. Я написал свою собственную функцию _strtok, которая использует strtok, но возвращает все токены в виде массива строк. Для тестирования я использую строку «ls -laR», определенную в функции main. Я получаю ошибку valgrind «Недопустимая запись размера 8» при попытке malloc количество символов во втором указателе в массиве строк с именем «Doubl». Почему он это делает? Я выделяю нужное количество указателей на строки в массиве doubl. Любая информация или помощь будут оценены

 #include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
char **_strtok(char *str, char *delim)
{
        char **doubl;
        char *s = str;
        char *string;
        int i = 0;

        while (*s)
        {
                if (*s == *delim)
                        i  ;
                s  ;
        }
        doubl = malloc(sizeof(char *) * i   1);
        i = 0;
        string = strtok(str, delim);
        while (1)
        {
                doubl[i] = malloc(sizeof(char) * strlen(string)   1);
                strcpy(doubl[i], string);
                i  ;
                if (string == NULL)
                        break;
                string = strtok(NULL, delim);
        }
        return (doubl);
}

char *get_path(char **env)
{
        char **check = env;
        char *path = NULL;
        char  pth[] = "PATH";
        int i, j, stop = 0;

        for (i = 0; check[i] amp;amp; stop == 0; i  )
        {
                for (j = 0; j < 4 amp;amp; stop == 0; j  )
                {
                        if (check[i][j] != pth[j])
                                break;
                        if (check[i][j] == pth[j] amp;amp; j == 3)
                        {
                                path = malloc(strlen(check[i]));
                                strcpy(path, check[i]);
                                stop = 1;
                        }
                }
        }
        return (path);
}

char **cmd_to_arg(char **cmd, char **env)
{

        /* FREE PATH BEFORE END */
        char *path = get_path(env);
        char *slash = "/";
        char **args = NULL, **check = _strtok(path, ":"), **checkStart = check, **cmdStart = cmd;
        int status = -1, i = 0, j;

        while (*checkStart)
        {
                strcat(*checkStart, slash);
                strcat(*checkStart, cmd[0]);
                status = access(*checkStart, F_OK | X_OK);
                printf("%sn", *checkStart);
                if (status == 0)
                        break;
                checkStart  ;
        }
        for(;*cmdStart; i  , cmdStart  )
                printf("%dn", i);
        args = malloc(sizeof(char *) * i);
        args[0] = malloc(strlen(*checkStart));
        strcpy(args[0], *checkStart);
        puts(args[0]);
        for (j = 1; j < i amp;amp; cmd[j] != NULL; j  )
        {
                //printf("%dn", j);
                args[j] = malloc(strlen(cmd[j]) * sizeof(char));
                strcpy(args[j], cmd[j]);
                puts(args[j]);
        }
        return (args);
}

int main(int ac, char **av, char **env)
{
        (void)ac, (void)av, (void)env;
        char line[] = "ls laR";
        //size_t size = 0;
        char **cmd; //**cmdStart;
        //int i = 0, j = 0;

        cmd = _strtok(line, " ");
        cmd = cmd_to_arg(cmd, env);
        return (0);
}


  

Комментарии:

1. Сколько указателей вы записываете в doubl? i 1? doubl достаточно велик только для i указателей плюс один дополнительный байт.

2. Примечание: в _strtok , if (*s == *delim) проверяет только текущий символ строки s на соответствие первому разделителю [другие разделители не проверяются]. Итак, передача " " работает, но " t" [или " ," ] не будет

3. Код в cmd_to_arg ожидает NULL , что в конце check [точно так же, как argv ] будет установлен терминатор. Но _strtok не выделяет для него пространство и не устанавливает его

4. И doubl = malloc(sizeof(char *) * i 1); слишком короткий. Из-за приоритета оператора это эквивалентно: doubl = malloc((sizeof(char *) * i) 1); то, что вы хотите, это: doubl = malloc(sizeof(char *) * (i 1));

5. Но это все равно не дает места для NULL , поэтому вы хотите: doubl = malloc(sizeof(char *) * (i 2)); И, вы хотите: doubl[i] = NULL; в конце функции.