Как очистить этот указатель массива в C? - PullRequest
2 голосов
/ 17 мая 2009

Я пытаюсь сделать базовый bash с использованием системных вызовов, но у меня есть небольшие проблемы с массивом указателей.

Чтобы возобновить мой код, я читаю команды из stdin с read () в буфер, затем использую strsep () для отделения команды от аргументов и всех аргументов в массив. Затем я создаю новый процесс с помощью fork () и выполняю эту команду со связанными аргументами с помощью execvp ().

Все это входит в бесконечный цикл до тех пор, пока пользователь не наберет "выход" (еще не закодирован). Проблема в том, что после первой итерации мне нужно, чтобы * pArgs был пустым для следующей команды и аргументов. И я не знаю, как это сделать ...

Вот мой код:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char **argv) {
    char bBuffer[BUFSIZ], *pArgs[10], *aPtr = NULL, *sPtr;
    int aCount;
    pid_t pid;

    while(1) {
        write(1, "\e[1;31mmyBash \e[1;32m# \e[0m", 27);
        read(0, bBuffer, BUFSIZ);

        sPtr = bBuffer;
        aCount = 0;

        do {
            aPtr = strsep(&sPtr, " ");
            pArgs[aCount++] = aPtr;
        } while(aPtr);

        pArgs[aCount-2][strlen(pArgs[aCount-2])-1] = '\0';

        // Debug code to output pArgs content
        write(1, "|>", 2);
        write(1, pArgs[0], strlen(pArgs[0]));
        write(1, "<|", 2);

        if(strlen(pArgs[0]) > 1) {
            pid = fork();

            if(pid == -1) {
                perror("fork");
                exit(1);
            }

            if(pid == 0) {
                execvp(pArgs[0], pArgs);
                exit(0);
            }
        }
    }

    return 0;
}

P.S: Извините, но я не могу предоставить тестовый пример ввода и вывода в данный момент. Надеюсь, это не так сложно понять и исправить, что вам, ребята, это не нужно. Я отправлю это позже, если это будет необходимо ...

Просто чтобы прояснить ситуацию:
Я знаю, я спросил, как очистить массив, и я получил ответ на это. Но теперь мне кажется очевидным, что моя проблема была не в этом, а в мусоре, который собирал буфер, как указано в litb. Логичнее завершать строку нулевым символом, чем очищать массив. Вот почему я отмечаю правильный ответ Литба.

Ответы [ 2 ]

7 голосов
/ 17 мая 2009
int i;
for (i = 0; i < 10; i++)
   pArgs[i] = NULL;
2 голосов
/ 17 мая 2009

Ваша проблема в том, что вы не добавляете нулевой символ после чтения данных. Так что звонки strsep не знают, где остановиться. В C строки должны заканчиваться нулевым символом (это называется завершающим нулевым символом).

// don't forget to add error handling at some point (s == -1)
ssize_t s = read(0, bBuffer, BUFSIZ-1);
bBuffer[s] = '\0';

Имея это в виду, я не вижу, какой массив должен быть очищен сейчас, так как execvp будет читать аргументы до первого нулевого указателя. Цикл do, однако, уже добавляет этот нулевой указатель, который является нулевым указателем, возвращаемым последним вызовом strsep.

Эту проблему, конечно, тоже можно решить, просто очистив bBuffer (данные, на которые указывает *pArgs после сканирования первой команды). Обратите внимание, что вы должны сделать это также перед первым сканированием, поскольку вы не можете предполагать, что символы в массиве bBuffer инициализируются любыми разумными значениями.

memset(bBuffer, 0, sizeof bBuffer);

Поместите это непосредственно перед вызовом read (но в любом случае читайте только максимально BUFSIZE-1, потому что завершающий нулевой символ тоже должен иметь пробел!).

Но, как я показал выше, вам не нужен этот вызов memset. Просто добавьте завершающий нулевой символ вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...