2015-08-11 2 views
0

Я честно понятия не имею, как происходит следующее. Вот код:Неожиданный вывод после первой итерации этого кода

while(1) 
{ 
    char** line = read_command(); 
    char* command = line[0]; 
    char** parameters = malloc(100); 
    int i; 

    for(i = 0; i < pNum; i++) // pNum is a global var containing the number of words read from read_command() 
    { 
     parameters[i] = line[i]; 
     printf("%i: %s", i, parameters[i]); 
    } 

    printf("%s\n", parameters[0]); 
    parameters[0] = "/usr/bin/"; 
    strcat(parameters[0], command); 
    printf("%s\n", command); 
    printf("%s\n", parameters[0]); 

    if(fork() != 0) 
     waitpid(1, &status, 0); 
    else 
     execve(parameters[0], parameters, NULL); 
} 

read_command() возвращает символ **, который в основном является «массив» на строку, которая была введена, и каждый символ * содержит слово. В результате, если я войду в «привет людей земли», результатом будет [«привет», «люди», «из», «земля»]. Эта функция всегда работает.

при первой итерации все работает так, как ожидалось. Например, когда я типа «дата» выход заключается в следующем:

0: date 
date 
date 
/usr/bin/date 
and then the date is displayed 

а на второй итерации, если я использую «дата» в качестве входного сигнала снова выход следующим образом:

0:date 
edate 
/usr/bin/datedate 
and the date command is not issued 

в второй оператор printf всегда печатает «e» после первой итерации, даже если я печатаю постоянную строку типа «привет». а затем параметры [0] каким-то образом имеют в себе 2 «дату», хотя указатель команды имеет только 1 «дату».

И после третьей итерации программа не ждет ввода пользователя, она просто перестает останавливаться и отображает «PM: предупреждение, таблица процессов заполнена!».

Что может быть причиной этого?

Я работаю в MINIX 3.1.0 с куб.см компилятор для C

EDIT: в read_command():

char* line = malloc(), * linep = line; 
size_t lenmax = 100, len = lenmax; 
int c; 
int currPos = 0; 
int currParam = 0; 
int i; 
char** parameters = malloc(100); 

if(line == NULL) 
    return NULL; 

while(1) 
{ 
    c = fgetc(stdin); 

    if(c == EOF) || c == '\n') 
     break; 

    if(--len == 0) 
    { 
     char* linen = realloc(linep, lenmax *= 2); 
     len = lenmax; 

     if(linen == NULL) 
     { 
      free(linep); 
      return NULL; 
     } 

     line = linen + (line - linep); 
     linep = linen; 
    } 

    if((*line++ = c) == '\n') 
     break; 
} 

*line = '\0'; // everything up to this point i got from this link: http://stackoverflow.com/a/314422/509914 

parameters[currentParam] = malloc(100); 

for(i = 0; i < strlen(linep); i++); 
{ 
    if(isspace(linep[i]) || line[i] == EOF) 
    { 
     parameters[currParam][currPos] = '\0; 
     currPos = 0; 
     parameters[++currParam] = malloc(100); 
    } 
    else 
     parameters[currParam][currPos++] = line[i]; 
} 

parameters[currParam][currPos] = '\0'; 
pNum = currParam + 1; 
return parameters; 
+1

Ваш 'printf ("% i:% s ", параметры [i]);' требуется два значения, а не один. Вероятно, это должно быть: 'printf ("% i:% s ", i, параметры [i]);' – cdarke

+1

'char ** parameters = malloc (100);' выделяет 100 байт, а не 100 лотов 'char * '. Возможно, вы имели в виду параметры 'char ** parameters = malloc (pNum * sizeof *),' – Sebivor

+0

@cdarke, спасибо, я изменил его. Это правильно в моем коде. –

ответ

1

Он уверен, что интересно, что те люди, которые учатся, читая авторитетные ресурсы , таких как проверенные и проверенные на протяжении десятилетий K & R, как правило, имеют эти проблемы гораздо реже, чем те, кто этого не делает ...

char** parameters = malloc(100); пытается выделить 100 байт. realloc ведет себя аналогично, поэтому я не буду упоминать об этом еще раз. Возможно, вы хотели выделить 100 лотов char *? Это было бы сделать еще больше смысла выделять pNum много char *: char **parameters = malloc(pNum * sizeof *parameters); ... char* linen = realloc(linep, (lenmax *= 2) * sizeof *linep); ...

strcat не выделяет память; единственными функциями, которые выделяют память, являются malloc, calloc и realloc.

Когда вы звоните strcat(foo, bar); вы просите strcat, чтобы добавить строку, на которую указывает bar на конец строки, на которую указывает foo. В вашем коде вы пытаетесь изменить строковый литерал. Неопределенное поведение и, как правило, segfault.

Даже ваша измененная попытка неверна. В parameters[0] = "/usr/bin/"; вы не копируете строку в parameters[0]; вы назначаете parameters[0], чтобы указать на строку (которая обычно находится в неизменяемой памяти, как я упоминал ранее). Вам действительно нужно сузить источник вашего неопределенного поведения, создав MCVE ...

В первой строке вашей read_command() функции, char* line = malloc(), * linep = line;, вы вызывали malloc без предоставления аргумента. Это нарушение ограничений. Ваш компилятор должен выдать вам сообщение об ошибке. Возможно, вы забыли #include <stdlib.h>, и поэтому у malloc отсутствует свой прототип? Пожалуйста, предоставьте MCVE, поэтому нам не нужно делать такие догадки.

Там другое нарушение ограничения на if(c == EOF) || c == '\n') ... Даже если бы мы должны были заполнить пробелы, чтобы произвести MCVE для вас (который мы не должны делать, потому что это ваша работа и вы спрашиваете нас за помощь), этот код не будет компилироваться. Возможно, это то, что вызывает ваши аварии? Всегда проверяйте сообщения, которые ваш компилятор дает вам. Не игнорируйте предупреждения ... и определенно не игнорируйте сообщения об ошибках.

Я сравнил код, который вы требовали, от this answer, и это совсем другое. Код для этого ответа компилируется для одного. Тем не менее, это ваш путь к установлению доверия с людьми, которые пытаются помочь вам ... лгать?

Вам не нужно столько динамического распределения, и, как правило, я бы сходил с пути и объяснил, как вы можете сделать это наилучшим образом, но ложь меня отпустила. У меня есть еще один момент: Удостоверьтесь, что parameters завершен нулевым указателем (аналогично тому, как строки заканчиваются нулевым символом), так как требуется the manual.

+1

* единственные функции, которые выделяют память *, включают 'calloc' и' alloca'? – cdarke

+0

Хорошо, я изменил эту часть на то, как это было в первый раз, когда я ее написал. Я изменил его, пытаясь найти ошибку. проверьте код. Проблема все еще сохраняется в ТОЧНОМ случае. :-) –

+0

@ArmandMaree: Вы пропустите момент, «первый раз, когда вы его написали», вероятно, был неправильным. Если у вас есть указатель на литерал, это должно быть 'const'. 'const char * greet =" Hello ";'. НИКОГДА не пропустите это 'const'. – cdarke