我遇到了一个我无法弄清楚的段错误。导致segmentation fault的函数如下所示:
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;
u_expr 和 expr_type 定义:
typedef union {
char *ident;
int intgr;
} u_expr;
typedef enum {
expr_Identifier,
expr_IntegerLiteral
} expr_type;
expr_type
是 expr_IntegerLiteral
和 expr_Identifier
的枚举。
根据GDB,段错误是由以下行引起的:the_exp->expr->intgr = intgr;
。
奇怪的是,它并不总是导致段错误 - 如果我以这种方式调用该函数,则会发生段错误:
Expression *e = IntegerLiteral_init(0);
但在我程序的另一部分,我使用以下方式调用它:
Expression *e;
...
e = IntegerLiteral_init(
(int)strtol(num_str, (char **)NULL, 10));
没有任何问题。 num_str
已从一些输入中解析出来,其值为 “0”
。
我不明白为什么我调用 IntegerLiteral_init()
的上下文会影响是否发生此段错误,如果给定的 intgr
参数相同。如果有人能阐明这一点,我将不胜感激。
最佳答案
线
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
时也释放 the_exp->expr
。
关于为什么 IntegerLiteral_init()
有时似乎有效,访问您尚未分配的内存会导致未定义的行为。有时你很幸运,这会立即崩溃,让你可以使用调试器来查看问题的确切位置。其他时候你就没那么幸运了,你的程序继续执行,只是在很久之后当其他一些代码试图访问内存 IntegerLiteral_init()
损坏时崩溃。
关于c - 段错误 - GNU C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17834589/