这个char ** 和后续char * 的内存分配是否正确?

问题描述 投票:0回答:1

我有以下结构定义,旨在表示时间序列图表:

/* MAX TICKS 24 HOURS * 60 MIN * 60 SEC */
#define MAX_TICKS 86400

/* CHART PARAMETERS */
typedef struct {

    /* DRAWING AREA WIDGET */
    Widget drawingArea;

    /* X-AXIS (TIME) */
    int x_tick_spacing_px;                  /* DISTANCE BETWEEN TIME TICKS IN PIXELS. */
    int x_num_ticks;                        /* TOTAL NUMBER OF TIME TICKS. */
    int *x_tick_values;                     /* ARRAY OF TIME TICK VALUES (E.G., 093000 FOR 09:30:00). */
    char **x_tick_labels;                   /* ARRAY OF TIME TICK LABELS, CORRESPONDING TO X_TICK_VALUES. */


} TSChart;

我正在编写一个解析器来处理定义 xaxis 定义的命令:

/* FUNCTION TO PARSE AND EXECUTE COMMANDS */
void parse_command(TSChart *chartData, char *command) {
    
    int arg_count;
    char **args;
    char *token;

    /* ALLOCATE MEMORY FOR ARGS */
    args = malloc(MAX_ARGS * sizeof(char *));
    if (args == NULL) {
        fprintf(stderr, "Memory allocation failed for args.\n");
        return;
    }

    /* INITIALIZE ARGUMENT COUNT TO ZERO */
    arg_count = 0;

    /* TOKENIZE THE COMMAND */
    token = strtok(command, " ");
    while (token != NULL && arg_count < MAX_ARGS) {
        args[arg_count++] = token;
        token = strtok(NULL, " ");
    }

    /* COMMAND PARSING */
    if (arg_count == 0) return;

    if(strcmp(args[0], "xaxis") == 0) { xaxis_command(chartData, arg_count - 1, args + 1); return; }

    fprintf(stderr, "ERROR: UNKNOWN COMMAND.\n");

    /* FREE THE ARGS ARRAY */
    free(args);
}

/* FUNCTION TO HANDLE THE "XAXIS" COMMAND */
void xaxis_command(TSChart *chartData, int arg_count, char **args) {
    
    int i;    
    int spacing;                /* TEMPORARY VARIABLE TO STORE SPACE BETWEEN TICKS IN PIXELS */
    int num_values;             /* TEMPORARY VARIABLE TO STORE THE NUMBER OF VALUES PASSED */
    int num_labels;             /* TEMPORARY VARIABLE TO STORE THE NUMBER OF LABELS PASSED */

    if (arg_count < 2) {
        fprintf(stderr, "ERROR: XAXIS COMMAND EXPECTS AT LEAST 2 ARGUMENTS.\n");
        return;
    }

    /* SPACING */
    if (strcmp(args[0], "spacing") == 0) {
        if (arg_count != 2) {
            fprintf(stderr, "ERROR: XAXIS SPACING EXPECTS 1 ARGUMENT.\n");
            return;
        }
        if (sscanf(args[1], "%d", &spacing) == 1) {
            chartData->x_tick_spacing_px = spacing;
        } else {
            fprintf(stderr, "ERROR: INVALID SPACING VALUE.\n");
        }
        return;
    } 

    /* VALUES */
    if (strcmp(args[0], "values") == 0) {
        if (arg_count < 2) {
            fprintf(stderr, "ERROR: XAXIS VALUES EXPECTS AT LEAST 1 ARGUMENT.\n");
            return;
        }
        num_values = atoi(args[1]);
        if (num_values != arg_count - 2) {
            fprintf(stderr, "ERROR: NUMBER OF VALUES DOES NOT MATCH EXPECTED COUNT.\n");
            return;
        }
        if (num_values > MAX_TICKS) {
            fprintf(stderr, "ERROR: NUMBER OF VALUES EXCEED MAXIMUM COUNT.\n");
            return;
        }
        chartData->x_num_ticks = num_values;
        chartData->x_tick_values = (int *)malloc(num_values * sizeof(unsigned int));
        if (chartData->x_tick_values == NULL) {
            fprintf(stderr, "ERROR: FAILED TO ALLOCATE MEMORY FOR X TICK VALUES.\n");
            return;
        }

        for (i = 0; i < num_values; i++) {
            chartData->x_tick_values[i] = atoi(args[i + 2]);
        }
        return;
    } 

    /* LABELS */
    if (strcmp(args[0], "labels") == 0) {
        if (arg_count < 2) {
            fprintf(stderr, "ERROR: XAXIS LABELS EXPECTS AT LEAST 1 ARGUMENT.\n");
            return;
        }
        num_labels = atoi(args[1]);
        if (num_labels != arg_count - 2) {
            fprintf(stderr, "ERROR: NUMBER OF LABELS DOES NOT MATCH EXPECTED COUNT.\n");
            return;
        }
        if (num_labels > MAX_TICKS) {
            fprintf(stderr, "ERROR: NUMBER OF LABELS EXCEED MAXIMUM COUNT.\n");
            return;
        }
        chartData->x_num_ticks = num_labels;
        chartData->x_tick_labels = (char **)malloc(num_labels * sizeof(char *));
        if (chartData->x_tick_labels == NULL) {
            fprintf(stderr, "ERROR: FAILED TO ALLOCATE MEMORY FOR X TICK LABELS.\n");
            return;
        }
        for (i = 0; i < num_labels; i++) {
            if(strcmp(args[i + 2], "_")==0) {
                chartData->x_tick_labels[i] = NULL;
            } else {
                chartData->x_tick_labels[i] = strdup(args[i + 2]);
            }
        }
        return;
    } 

    /* UNKNOWN SUBCOMMAND */
    fprintf(stderr, "ERROR: UNKNOWN XAXIS SUBCOMMAND.\n");
    
}

设置 x_tick_spacing_px 和 int *x_tick_values 的子命令工作正常。 然而,设置 char **x_tick_labels 会导致“中止陷阱” - 没有提供更多详细信息 -

char **x_tick_labels 的内存分配以及后续各个字符串的分配是否正确完成?

编辑:

我已根据评论更正了各个字符串的分配:

/* FUNCTION TO PARSE AND EXECUTE COMMANDS */
void parse_command(TSChart *chartData, char *command) {

    int i;  
    int arg_count;
    char **args;
    char *token;
    
    /* ALLOCATE MEMORY FOR ARGS */
    args = (char **)malloc(MAX_ARGS * sizeof(char *));
    if (args == NULL) {
        fprintf(stderr, "Memory allocation failed for args.\n");
        return;
    }

    /* INITIALIZE ARGUMENT COUNT TO ZERO */
    arg_count = 0;

    /* TOKENIZE THE COMMAND */
    token = strtok(command, " ");
    while (token != NULL && arg_count < MAX_ARGS) {
        args[arg_count] = strdup(token);
        token = strtok(NULL, " ");
        fprintf(stderr, "DEBUG cli.c arg_count %d token %s\n", arg_count, token);
        arg_count++;
    }

    /* COMMAND PARSING */
    if (arg_count == 0) return;

    if(strcmp(args[0], "redraw") == 0) redraw_command(chartData); 
    else if(strcmp(args[0], "line") == 0) line_command(chartData, arg_count, args); 
    else if(strcmp(args[0], "xaxis") == 0) xaxis_command(chartData, arg_count, args); 
    else fprintf(stderr, "ERROR: UNKNOWN COMMAND.\n");

    /* FREE THE ARGS ARRAY */
    for(i=0; i<arg_count; i++) free(args[i]);
    free(args);
}

我还包括处理命令本身的函数:


/* FUNCTION TO HANDLE THE "XTICK" COMMAND */
void xaxis_command(TSChart *chartData, int arg_count, char **args) {
    
    int i;    
    int spacing;                /* TEMPORARY VARIABLE TO STORE SPACE BETWEEN TICKS IN PIXELS */
    int num_values;             /* TEMPORARY VARIABLE TO STORE THE NUMBER OF VALUES PASSED */
    int num_labels;             /* TEMPORARY VARIABLE TO STORE THE NUMBER OF LABELS PASSED */

    if (arg_count < 3) {
        fprintf(stderr, "ERROR: XAXIS COMMAND EXPECTS AT LEAST 2 ARGUMENTS.\n");
        return;
    }

    /* SPACING */
    if (strcmp(args[1], "spacing") == 0) {
        if (arg_count != 3) {
            fprintf(stderr, "ERROR: XAXIS SPACING EXPECTS 1 ARGUMENT.\n");
            return;
        }
        if (sscanf(args[2], "%d", &spacing) == 1) {
            chartData->x_tick_spacing_px = spacing;
        } else {
            fprintf(stderr, "ERROR: INVALID SPACING VALUE.\n");
        }
        return;
    } 

    /* VALUES */
    if (strcmp(args[1], "values") == 0) {
        if (arg_count < 3) {
            fprintf(stderr, "ERROR: XAXIS VALUES EXPECTS AT LEAST 1 ARGUMENT.\n");
            return;
        }
        num_values = atoi(args[2]);
        if (num_values != arg_count - 3) {
            fprintf(stderr, "ERROR: NUMBER OF VALUES DOES NOT MATCH EXPECTED COUNT.\n");
            return;
        }
        if (num_values > MAX_TICKS) {
            fprintf(stderr, "ERROR: NUMBER OF VALUES EXCEED MAXIMUM COUNT.\n");
            return;
        }
        chartData->x_num_ticks = num_values;
        chartData->x_tick_values = (int *)malloc(num_values * sizeof(unsigned int));
        if (chartData->x_tick_values == NULL) {
            fprintf(stderr, "ERROR: FAILED TO ALLOCATE MEMORY FOR X TICK VALUES.\n");
            return;
        }

        for (i = 0; i < num_values; i++) {
            chartData->x_tick_values[i] = atoi(args[i + 3]);
        }
        return;
    } 

    /* LABELS */
    if (strcmp(args[1], "labels") == 0) {
        if (arg_count < 3) {
            fprintf(stderr, "ERROR: XAXIS LABELS EXPECTS AT LEAST 1 ARGUMENT.\n");
            return;
        }
        num_labels = atoi(args[2]);
        if (num_labels != arg_count - 3) {
            fprintf(stderr, "ERROR: NUMBER OF LABELS DOES NOT MATCH EXPECTED COUNT.\n");
            return;
        }
        if (num_labels > MAX_TICKS) {
            fprintf(stderr, "ERROR: NUMBER OF LABELS EXCEED MAXIMUM COUNT.\n");
            return;
        }
        chartData->x_num_ticks = num_labels;
        fprintf(stderr, "num_labels %d\n", num_labels);
        chartData->x_tick_labels = (char **)malloc(num_labels * sizeof(char *));
        if (chartData->x_tick_labels == NULL) {
            fprintf(stderr, "ERROR: FAILED TO ALLOCATE MEMORY FOR X TICK LABELS.\n");
            return;
        }
        for (i = 0; i < num_labels; i++) {
            if(strcmp(args[i + 3], "_")==0) {
                chartData->x_tick_labels[i] = NULL;
            } else {
                chartData->x_tick_labels[i] = strdup(args[i + 3]);
            }
        }
        goto DEBUG;
        return;
    } 

    /* UNKNOWN SUBCOMMAND */
    fprintf(stderr, "ERROR: UNKNOWN XTICK SUBCOMMAND.\n");
   
DEBUG: 
    fprintf(stderr, "DEBUG cli.c xaxis_command() | chartData->x_num_ticks %d\n", chartData->x_num_ticks);
    fprintf(stderr, "DEBUG cli.c xaxis_command() | chartData->x_tick_labels %p\n", chartData->x_tick_labels);
    for(i=0; i<chartData->x_num_ticks; i++) {
        if(chartData->x_tick_labels[i] != NULL) fprintf(stderr,"x_tick_labels[%d] = #%s#\n", i, chartData->x_tick_labels[i]);
    }
}

但仍然是相同的中止陷阱。该过程已正确完成,并且在出现 Abort trap 消息之前不会执行相关结构的读取。

c c89
1个回答
0
投票

这个答案指的是问题中的发布的第二块代码

char **x_tick_labels 的内存分配以及后续各个字符串的分配是否正确完成?

是的,看起来是正确的。您的分配/释放没有明显的错误。

但是您的代码还存在一些其他问题。

#1:

在这一部分

while (token != NULL && arg_count < MAX_ARGS) {
    args[arg_count] = strdup(token);
    token = strtok(NULL, " ");
    fprintf(stderr, "DEBUG cli.c arg_count %d token %s\n", arg_count, token);
    arg_count++;
}

fprintf
被称为 after 更新
token

#2:

在这一部分

/* UNKNOWN SUBCOMMAND */
fprintf(stderr, "ERROR: UNKNOWN XTICK SUBCOMMAND.\n");


DEBUG: 
    fprintf(stderr, "DEBUG cli.c xaxis_command() | chartData->x_num_ticks %d\n", chartData->x_num_ticks);

a

return
缺失。如果没有它,您就开始使用未初始化的变量。

#3:

在这一部分

    args[arg_count] = strdup(token);

没有检查

strdup
返回
NULL
,因此
args[arg_count]
可能会获得值
NULL
。下面的代码以无法接受
args
的方式使用
NULL
。因此,要么您需要在此处进行
NULL
检查,要么必须更改以下代码以处理
NULL

© www.soinside.com 2019 - 2024. All rights reserved.