Problemi a creare una shell in c (Seg-Fault e Ferror)
-
13-12-2019 - |
Domanda
Ho seguito un tutorial su come fare il mio shell ma sono stato bloccato per un paio di giorni.
Due cose:
- .
- Quando questo codice è compilato e correva, avrà casualmente i guasti di segmentazione e non riesco a capire perché.
- L'istruzione if `If (Ferror!= 0)` Sembra sempre vero.Che è strano perché non capisco perché Fets () è in errore nella funzione Main () .
Qualsiasi informazione su questi argomenti (o altri argomenti sulla creazione di questo shell) sarebbe molto apprezzata.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#define MAXSIZE 512
int parseCmd(char *cmd, char *args[])
{
printf("LOGGER: parseCmd(cmd=%s, args=%p)\n", cmd, args);
char cmdDelims[] = {' ','>'};
char *cmdReader;
cmdReader = strtok(cmd, cmdDelims);
int i = 0;
while (cmdReader != NULL)
{
args[i] = strdup(cmdReader);
printf("LOGGER: args[%d]=%s\n", i, args[i]);
cmdReader = strtok(NULL, cmdDelims);
i++;
}
return 0;
}
void printToLine(char *args[])
{
int length;
length = sizeof(args) / sizeof(char);
int i = 0;
while (i < length)
{
printf("%s\n", args[i]);
i++;
}
}
int main(int argc, char *argv[])
{
char *in;
in = malloc(MAXSIZE);
char *args[15];
char *cmd = NULL;
int errorBit = 0;
int terminationBit = 1;
char error_message[30] = "An error has occurred\n";
char inDelims[] = "\n";
while (terminationBit)
{
printf("mysh>");
// get input from command line
fgets(in, MAXSIZE, stdin);
if (ferror != 0)
{
perror(error_message);
}
// get pointer to command line input w/o the newline
cmd = strtok(in, inDelims);
// parse the command into separate arguments
errorBit = parseCmd(cmd, args);
if (errorBit)
{
perror(error_message);
exit(1);
}
printToLine(args);
// check if the user wants to exit the shell
if (strcmp(*args, "exit") == 0)
{
terminationBit = 0;
}
}
return 0;
}
.
Ecco alcune uscite:
**[ray@12] (6)$ mysh**
mysh>1 2 3
An error has occurred
: Success
LOGGER: parseCmd(cmd=1 2 3, args=0x7fff4a50b080)
LOGGER: args[0]=1
LOGGER: args[1]=2
LOGGER: args[2]=3
1
2
3
Segmentation fault (core dumped)
**[ray@12] (7)$ mysh**
mysh>1 2 3 4 5 6 7 8 9 10
An error has occurred
: Success
LOGGER: parseCmd(cmd=1 2 3 4 5 6 7 8 9 10, args=0x7fffba053d70)
LOGGER: args[0]=1
LOGGER: args[1]=2
LOGGER: args[2]=3
LOGGER: args[3]=4
LOGGER: args[4]=5
LOGGER: args[5]=6
LOGGER: args[6]=7
LOGGER: args[7]=8
LOGGER: args[8]=9
LOGGER: args[9]=10
1
2
3
4
5
6
7
8
mysh>1 2 3
An error has occurred
: Success
LOGGER: parseCmd(cmd=1 2 3, args=0x7fffba053d70)
LOGGER: args[0]=1
LOGGER: args[1]=2
LOGGER: args[2]=3
1
2
3
4
5
6
7
8
.Soluzione
Per l'errore ferror
, è necessario testare ferror(stdin)
, non ferror
.Quest'ultimo è l'indirizzo della funzione, che non sarà mai zero:
if (ferror(stdin) != 0)
{
perror(error_message);
}
.
Per almeno alcuni dei segfault, questo non fa quello che pensi:
length = sizeof(args) / sizeof(char);
.
Questo ti dirà quanti byte vengono utilizzati per memorizzare il puntatore , che è 4 o 8 a seconda, e non il numero di argomenti.
Quindi se si dispone di quattro (o otto) argomenti, lo farà per funzionare.Se ne hai di più, sembrerà ignorare alcuni argomenti.E se hai meno, recupererà gli argomenti mancanti dall'altra parte del vuoto, con conseguente (quasi sicuro) Guasto di segmentazione.
È necessario calcolare length
in modo indipendente e passarlo avanti o memorizzare un po 'di terminatore in args
, ad esempio aggiungendo un argomento null dopo l'ultimo argomento valido che trovi:
cmdReader = strtok(NULL, cmdDelims);
i++;
}
args[i] = NULL;
return 0;
}
void printToLine(char *args[])
{
int i = 0;
while (args[i])
{
printf("%s\n", args[i]);
i++;
}
}
.