简体   繁体   中英

I'm writing a shell in C and I am having trouble with pointers to char arrays in a struct

When I run my code the first printParams() call works perfectly. But every call after fork() the struct loses all of its char array values. I'm not that knowledgeable of pointers, but I can tell that the root of this problem is probably pointer-based. For example, the first printParams() will print out all of the values assigned in the Parse() function. But after the fork() , all of the integer values such as background and argumentCount are displayed but none of the string values associated with inputRedirect or the string values held in the vectorArguments array.

![Here is a photo of my output]] 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "parse.h"

void printParams(Param_t * param);

struct PARAM
{
    char *inputRedirect;           /* file name or NULL */
    char *outputRedirect;          /* file name or NULL */
    int background;                /* ethier 0 (false) or 1 (true) */
    int argumentCount;             /* number of tokens in argument vector 
    */
    char *argumentVector[MAXARGS]; /* array of String */
};

typedef struct PARAM Param_t;

int main(int argc, char *argv[]){
    int i;
    int debug;
    pid_t pid;
    
    if(argc>1){
        if(!strcmp(argv[1], "-debug"))
            debug = 1;
    }
   
    Param_t * testParam = Parse();
    
    if(debug == 1){
        printParams(testParam);
    }

    pid = fork();       
    printParams(testParam);
    
    if(pid == 0){
        exit(1);
    }       
    return 0;
}

void printParams(Param_t *param)
{
    int i;
    
    printf("InputRedirect: [%s]\n", (param->inputRedirect != NULL) ? param-
    >inputRedirect: "NULL");
    printf("OutputRedirect: [%s]\n", (param->outputRedirect != NULL) ? 
    param->outputRedirect: "NULL");
    printf ("Background: [%d]\n", param->background);
    printf ("ArgumentCount: [%d]\n", param->argumentCount);
    
    for (i = 0; i < param->argumentCount; i++)
        printf("ArgumentVector[%2d]: [%s]\n", i, param->argumentVector[i]);     
}

Param_t* Parse(){
    char *toke[MAXARGS];
    int i = 0;
    char str[MAXSTRLENGTH];
    int j;
    int k=0;
    
    Param_t* testParam = malloc(sizeof(Param_t));
    testParam->argumentCount = 0;
    
    printf("Enter your commands:\n");
    fgets(str, MAXSTRLENGTH, stdin);
    
    toke[i] = strtok(str, " ");

    //Tokenizes the user input into the toke array
    while(toke[i] != NULL){
        //printf("%s\n", toke[i]);
        ++i;
        toke[i] = strtok(NULL, " ");
    }
    
    i=0;  
    char c;
    
    while(toke[i] != NULL){
        c = toke[i][0];
        if(c == '<')
        {
            for(j=0; j<strlen(toke[i]); ++j ){
                toke[i][j] = toke[i][j+1];
            }
            testParam->inputRedirect = toke[i];
        }
        else if(c == '>')
        {
            for(j=0; j<strlen(toke[i]); ++j ){
                toke[i][j] = toke[i][j+1];
            }
            testParam->outputRedirect = toke[i];
        }
        else if(c == '&')
        {
            testParam->background = 1;
            //background  
        }
        else
        {
            testParam->argumentVector[k] = toke[i];
            k++;
            //save as cmd vector
        }
        ++i;
    }   
    testParam->argumentCount = k;
    return testParam;
}

The reason you loose all char * values is because strtok() function doesn't create buffer. Basically all your char* consist of an address pointing into str variable you read with fgets() . The str variable has scope only to end of Parse() function.

Solution for this:

Replace:

testParam->inputRedirect = toke[i];

with:

testParam->inputRedirect = malloc(MAXSTRLENGTH);
memset( testParam->inputRedirect, 0, MAXSTRLENGTH);
memcpy( testParam->inputRedirect, toke[i], strlen(toke[i]) );

But please note, that this leads to memory leak since there is no free() .

Sugestion:

Create static instance of structure in main and give its pointer to Parse function.

Param_t testParam;
Parse( &testParam );

Let the Parse function fill it. And at the end of main call free for all char * buffers inside testParam

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM