我一直有一个分割错误,我想不出来。导致分割错误的功能如下:

Expression *IntegerLiteral_init(int intgr) {
    Expression *the_exp = safe_alloc(sizeof(Expression));
    the_exp->type = expr_IntegerLiteral;
    the_exp->expr->intgr = intgr;
    the_exp->exec_count = 0;
    return the_exp;
}

定义表达式:
typedef struct {
    expr_type type;
    u_expr *expr;
    int exec_count;
} Expression;

定义了表达式和表达式类型:
typedef union {
    char *ident;
    int intgr;
} u_expr;

typedef enum {
    expr_Identifier,
    expr_IntegerLiteral
} expr_type;

expr_typeexpr_IntegerLiteralexpr_Identifier的枚举。
根据gdb,segfult是在线路上引起的:the_exp->expr->intgr = intgr;
奇怪的是,它并不总是导致segfault—如果我以这种方式调用函数,就会发生segfault:
Expression *e = IntegerLiteral_init(0);

但在我程序的另一部分中,我称之为使用:
Expression *e;

...

e = IntegerLiteral_init(
    (int)strtol(num_str, (char **)NULL, 10));

没有任何问题。num_str已从某些输入中解析,其值为"0"
我不明白,如果给定的IntegerLiteral_init()参数相同,为什么我调用intgr的上下文会影响此segfult是否发生。如果有人能告诉我,我将不胜感激。

最佳答案

线路

the_exp->expr->intgr = intgr;

正在写入未初始化的指针。您为the_exp分配了内存,但没有为the_exp->expr分配内存。最简单的解决方法可能是通过值而不是指针将Expression更改为u_expr
typedef struct {
    expr_type type;
    u_expr expr;
    int exec_count;
} Expression;

如果您不能这样做,IntegerLiteral_init可以更改为分配the_exp->expr的内存
Expression *IntegerLiteral_init(int intgr) {
    Expression *the_exp = safe_alloc(sizeof(Expression));
    the_exp->type = expr_IntegerLiteral;
    the_exp->expr = safe_alloc(sizeof(*the_exp->expr));
    the_exp->expr->intgr = intgr;
    the_exp->exec_count = 0;
    return the_exp;
}

如果您尝试后一种方法,请确保在释放the_exp->expr时也释放the_exp
关于为什么有时IntegerLiteral_init()看起来有效,访问未分配的内存会导致未定义的行为。有时你很幸运,但这会立即崩溃,让你可以使用调试器来查看问题所在。其他时候,你运气不好,程序继续执行,但在很长一段时间后,当另一位代码试图访问内存IntegerLiteral_init()时崩溃。

07-26 03:15