Pregunta

He estado siguiendo un tutorial sobre cómo hacer mi propio caparazón, pero llevo un par de días estancado.

Dos cosas:

  1. Cuando este código se compila y ejecuta, tendrá fallas de segmentación aleatoriamente y no puedo entender por qué.
  2. La declaración if `if (ferror! = 0)` siempre parece ser cierta.lo cual es raro porque no entiendo por qué fget() está fallando en el principal() función.

Cualquier información sobre estos temas (u otros temas sobre la creación de este shell) será muy apreciada.

#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;
}

A continuación se muestran algunos resultados:

**[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
¿Fue útil?

Solución

Para el ferror error, necesitas probar ferror(stdin), no ferror.Esta última es la dirección de la función, que nunca será cero:

if (ferror(stdin) != 0)
{
    perror(error_message);
}

Al menos para algunos de los fallos de segmento, esto no hace lo que piensas:

length = sizeof(args) / sizeof(char);

esto te dira ¿Cuántos bytes se utilizan para almacenar el puntero?, que es 4 u 8 dependiendo, y no el número de argumentos.

Entonces, si tiene cuatro (u ocho) argumentos, será aparecer trabajar.Si tiene más, parecerá ignorar algunos argumentos.Y si tiene menos, buscará los argumentos que faltan a través del Vacío, lo que resultará en una falla de segmentación (casi segura).

necesitas calcular length independientemente y pasarlo, o almacenar algún terminador en args, por ejemplo agregando un argumento NULL después del último argumento válido que encuentre:

        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++;
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top