Выделение памяти для массива на указатель на символ - PullRequest
3 голосов
/ 25 мая 2010

Следующий фрагмент кода дает ошибку сегментации при выделении памяти для последнего аргумента.Что я делаю неправильно?Спасибо.

    int n_args = 0, i = 0;
    while (line[i] != '\0')
    {
        if (isspace(line[i++]))
            n_args++;
    }

    for (i = 0; i < n_args; i++)
        command = malloc (n_args * sizeof(char*));

    char* arg = NULL;
    arg = strtok(line, " \n");
    while (arg != NULL)
    {
        arg = strtok(NULL, " \n");
            command[i] = malloc ( (strlen(arg)+1) * sizeof(char) );
        strcpy(command[i], arg);
        i++;
    }

Спасибо.

Ответы [ 7 ]

4 голосов
/ 25 мая 2010

Вы не сбрасываете значение i после цикла for, поэтому i равно n_args при достижении нижнего блока. Попытка доступа к command[i] в этот момент приводит к обращению к неинициализированной памяти и ошибкам сегмента.

Настоящий урок здесь состоит в том, чтобы не использовать переменные таким образом без уважительной причины. Ваш код будет более надежным и легким для чтения, если вы будете использовать что-то отличное от i в середине цикла for.

2 голосов
/ 25 мая 2010
for (i = 0; i < n_args; i++)
        command = malloc (n_args * sizeof(char*));

должно стать просто

command = malloc (n_args * sizeof(char*))

потому что вы просто хотите выделить массив элементов n_args, а

while (arg != NULL)
    {
        arg = strtok(NULL, " \n");
        command[i] = malloc ( (strlen(arg)+1) * sizeof(char) );
        strcpy(command[i], arg);
        i++;
    }

должно стать:

arg = strtok(NULL, " \n");
while (arg != NULL) {
    command[i] = malloc ( (strlen(arg)+1) * sizeof(char) );
    strcpy(command[i], arg);
    i++;
    arg = strtok(NULL, " \n");
}

чтобы избежать strlen для нулевого указателя.

0 голосов
/ 26 мая 2010

Трудно понять, что вы пытаетесь сделать.

Похоже, вы смотрите на количество пробелов в командной строке, чтобы увидеть, сколько аргументов командной строки у вас есть. Являются ли все ваши аргументы командной строки одним символом? Malloc резервирует достаточно места только для одного символа в аргументе.

Если ваши аргументы состоят из одного символа:

command = malloc(strlen(line));
i = 0;
j = 0;
while(line[j]) {
   if(!isspace(line[j])){
      command[i++] = line[j];
   }
   j++;
}
0 голосов
/ 26 мая 2010

Попробуйте правильно организовать этот цикл:

 while (arg != NULL)
    {
        arg = strtok(NULL, " \n");
            command[i] = malloc ( (strlen(arg)+1) * sizeof(char) );
        strcpy(command[i], arg);
        i++;
    }

строка "arg = strtok ..." делает 2 ошибки:

  1. Пропускает первый аргумент.
  2. Не проверяет код возврата, поэтому, если arg == NULL, то strlen (arg) будет SEGFAULT.

Сделайте это вместо:

 while (arg != NULL)
    {
        command[i] = malloc ( (strlen(arg)+1) * sizeof(char) );
        strcpy(command[i], arg);
        i++;
        arg = strtok(NULL, " \n");
    }
0 голосов
/ 25 мая 2010

Ты выбрасываешь свой первый аргумент? Это намеренно? Если это не

int n_args = 1;     /* We need one element more than spaces */
int i = 0;
while (line[i])
{
    if (isspace(line[i++]))
        n_args++;
}

command = malloc (n_args * sizeof(char*));

char* arg = NULL;
arg = strtok(line, " \n");
i = 0;        /***** You forgot to reset that value, that was your segfault !!! */
while (arg)
{
    command[i++] = strdup(arg);  /* It does your malloc/strlen/strcpy */
    arg = strtok(NULL, " \n");
}

Вы забыли сбросить индекс i, который выходит за пределы выделенного массива в вашем коде.

0 голосов
/ 25 мая 2010

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

Этот блок:

for (i = 0; i < n_args; i++)
    command = malloc (n_args * sizeof(char*));

Должно быть так:

    command = malloc (n_args * sizeof(char*));

Нет необходимости перераспределять command снова и снова.

Что касается ошибки сегмента, возможно, это связано с тем, что вы повторно используете переменную i, не сбрасывая ее снова в ноль.

0 голосов
/ 25 мая 2010

Для строки, содержащей два аргумента, разделенных одним пробелом, n_args будет 1, а не 2. Это, вероятно, не то, что вы хотите.

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