【问题标题】:The value of my struct is not updated when passing a malloced pointer传递 malloced 指针时,我的结构的值未更新
【发布时间】:2020-03-29 22:26:35
【问题描述】:

我正在为 shell 实现历史记录。我有一个存储命令的结构,这些结构的数组存储历史记录。

typedef struct command {
    char **arg;
    int num;
} cmd;

下面的代码正确更新历史,打印出来

命令#1:ls -l

Cmd #1:密码

命令#2:ls -l

int main() {
    char *arguments[3] = {"ls", "-l", NULL};
    cmd *history = startHist();
    history = updateHist(arguments, history);
    printHistory(history);
    char *arg2s[2] = {"pwd", NULL};
    history = updateHist(arg2s, history);
    printHistory(history);
    free(history);
}

cmd* startHist() {
    cmd *ret = malloc(20*sizeof(cmd));
    for(int i=0;i<20;i++){
        ret[i].arg = NULL;
        ret[i].num = -1;
    }
    return ret;
}

cmd* updateHist(char **args, cmd *hist) {
    for(int i = 19;i>0;i--) {
        hist[i] = hist[i-1];
    }
    hist[0].arg = args;
    if(hist[1].arg!=NULL) {
        hist[0].num = hist[1].num+1;
    } else {
        hist[0].num = 1;
    }
    return hist;
}

void printHist(cmd *hist) {
    int pos = 0;//index for iterating through commands
    while(hist[pos].arg!=NULL) {
        char* prstr = malloc(INIT_BUFFER*sizeof(char));//the string that will be printed
        *prstr = '\0';
        int index = 0;//index for iterating through arguments
        printf("Cmd #%d: ", pos+1);
        while(hist[pos].arg[index] != NULL) {
            printf("%s ", hist[pos].arg[index]);
            strcat(prstr, hist[pos].arg[index]);//concatenate the argument strings
            index++;
        }
        printf("\n");
        pos++;
        free(prstr);
    }
}

但是,以下代码无法运行。每个 cmd 条目的字符串值被替换为最近的命令,尽管 int 值正常工作。

编辑:已根据建议修改代码。它现在应该运行 3 个输入循环。 示例输出:

?: ls

Cmd #1:ls

?: ls -a

命令#1:ls -a

命令#2:ls -a

?: 退出

Cmd #1:退出

Cmd #2:退出

Cmd #3:退出

注意startHist()、printHist()和updateHist()同上。

#include "stdio.h"//get from and print to console
#include "stdlib.h"//free and malloc
#include <string.h>//strtok

//Initial input buffer size. Will be expanded in getLine if needed.
const int INIT_BUFFER = 256;

typedef struct command {
    char **arg;
    int num;
} cmd;

//Function Declarations
char * getLine();//gets the input from the console and returns it
char ** splitLine(char *a);//splits the passed string into argument substrings
cmd* updateHist(char **args, cmd *hist);
void printHist(cmd *hist);
cmd* startHist();

void main() {
    //declare primary variables
    char *input;
    char **args;
    int retVal=3;
    cmd *history = startHist();
    do {//primary execution loop
        printf("?: ");//prompt for input
        input = getLine();
        args = splitLine(input);
        history = updateHist(args, history);
        printHist(history);
        retVal--;
        free(input);
        free(args);
    } while(retVal);
    free(history);
}

char ** splitLine(char *input) {
    //variables for finding the number and length of the arguments
    int numArgs=1;//the number of args in the input(starts at 1, increases per space).
    int pos = 0;//the position as the input is iterated through
    //loop to find the number and length of the arguments
    while(input[pos]!='\0'){//until the end of the input is reached
        if(input[pos]==' '){//if the end of the argument is reached
            numArgs++;//increment argument counter
        }
        pos++;//increment the position counter
    }
    pos=0;//reset pos to reiterate through the input
    //create an array of arguments
    char* *argArray = malloc((1+numArgs)*sizeof(char*));
    char *temp = strtok(input, " \n\r\t");//get the first token from the string
    while(temp!=NULL) {
        argArray[pos] =temp;
        pos++;
        temp=strtok(NULL, " \n\r\t");
    }
    argArray[pos]=NULL;
    return argArray;
}

char * getLine() {
    int buffspace = INIT_BUFFER;
    char *buffer = malloc(sizeof(char)*INIT_BUFFER);
    int pos = 0;
    int c;//input 
    
    if(!buffer) {
        fprintf(stderr, "Shell: Allocation Error\n");
        exit(EXIT_FAILURE);
    }
    
    do {
        c=getchar();//get the next character
        
        if(c==EOF || c=='\n'||c=='\r') {
            buffer[pos]='\0';
            return buffer;
        } else {
            buffer[pos] = c;
        }
        pos++;
        
        if(pos>=buffspace) {
            buffspace += INIT_BUFFER;
            buffer = realloc(buffer, buffspace);
        }
    } while(c!=EOF);
    
    //the buffer should be returned before this point.
    //Print out an error and exit
    fprintf(stderr, "Shell: Assignment Error\n");
    return buffer;
}

cmd* startHist() {
    cmd *ret = malloc(20*sizeof(cmd));
    for(int i=0;i<20;i++){
        ret[i].arg = NULL;
        ret[i].num = -1;
    }
    return ret;
}

cmd* updateHist(char **args, cmd *hist) {
    for(int i = 19;i>0;i--) {
        hist[i] = hist[i-1];
    }
    hist[0].arg = args;
    if(hist[1].arg!=NULL) {
        hist[0].num = hist[1].num+1;
    } else {
        hist[0].num = 1;
    }
    return hist;
}

void printHist(cmd *hist) {
    int pos = 0;//index for iterating through commands
    while(hist[pos].arg!=NULL) {
        char* prstr = malloc(INIT_BUFFER*sizeof(char));//the string that will be printed
        *prstr = '\0';
        int index = 0;//index for iterating through arguments
        printf("Cmd #%d: ", pos+1);
        while(hist[pos].arg[index] != NULL) {
            printf("%s ", hist[pos].arg[index]);
            strcat(prstr, hist[pos].arg[index]);//concatenate the argument strings
            index++;
        }
        printf("\n");
        pos++;
        free(prstr);
    }
}

【问题讨论】:

  • 请提供minimal verifiable example。调试不完整的代码效率不高,因为问题甚至可能不在显示的内容中。例如,getLine 做什么?我们怎么知道它没有返回静态内存或更糟的是,一个局部变量?
  • @kaylum 对此感到抱歉。我更新了代码,现在它可以独立运行了。

标签: c pointers


【解决方案1】:

看起来您只是将指针存储在 cmd 数据结构中,而不是指向字符串和数组。这意味着您最终会在局部变量超出范围后保存指向它们的指针,这会导致未定义的行为。

【讨论】:

    猜你喜欢
    • 2021-03-13
    • 1970-01-01
    • 1970-01-01
    • 2013-09-02
    • 2012-04-04
    • 1970-01-01
    • 2014-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多