更改结构字符串

时间:2013-10-11 14:31:00

标签: c struct segmentation-fault lex c-strings

我正在使用lex来实现扫描程序。我想在解析时构建一个符号表。我有两个结构,SymbolEntry和SymbolTable(下面)。大多数时候,当我调用我的函数插入符号(registerID,也在下面)时,我有条目的所有信息。但是,当我有一个常量时,我​​也希望得到它的值,但是当我第一次创建条目时,这并不是立即可用的。当我尝试在代码中稍后更改条目值时,我将使该条目使用的整个内存块无效,并且名称和值正在打印垃圾。

以下是两个结构:

typedef struct{
    char* type;
    char* name;
    char* value;
} SymbolEntry;
typedef struct{
    SymbolEntry *entries;
    size_t size;
    size_t capacity;
} SymbolTable;

这是registerID函数,在{id}匹配时调用。 yytext包含ID。

int registerID(char* type){
    //create a new symbol entry with the specified type and name and a default value
    SymbolEntry e;
    e.type = type;
    e.name = (char *)calloc(yyleng+1, sizeof(char));
    strcpy(e.name, yytext);
    e.value = "";
    prevSym = insertSymbol(&table, e);
    return prevSym;
}

这是insertSymbol(SymbolTable* st, SymbolEntry entry)的相关代码。插入时pos始终是数组中的最后一个元素(否则该条目不唯一,只返回pos)。

st->entries[pos].name = (char *)calloc(strlen(entry.name)+1, sizeof(char));
st->entries[pos].type = (char *)calloc(strlen(entry.type)+1, sizeof(char));
st->entries[pos].value = (char *)calloc(strlen(entry.value)+1, sizeof(char));
strcpy(st->entries[pos].name, entry.name);
strcpy(st->entries[pos].type, entry.type);
strcpy(st->entries[pos].value, entry.value);

稍后,在lex框架紧跟CONSTANTs名称之后的值匹配之后,将执行此代码(直接在<CONSTANT_VAL>{number}的规则中)

table.entries[prevSym].value = (char *)calloc(yyleng+1, sizeof(char));
strcpy(table.entries[prevSym].value, yytext);

为什么这会使数组中此位置的SymbolEntry无效,如何安全地更改value的内容?

修改   它不仅发生在常数上。前两个SymbolEntry总是垃圾。我假设这可能意味着他们都是,但其他人都没有被覆盖。

此外,似乎后续调用registerID会导致数据损坏。只有9个符号,只有前两个是垃圾,有34个,它是第7个。添加更多文本来解析没有变量不会导致任何问题。

解决 好吧,事实证明,我只是偶然地删除了一路上的某条线路,这就是引入该错误的原因。我不小心删除了对initSymbolTable的电话。感谢chux问我如何初始化表格。对不起。

1 个答案:

答案 0 :(得分:1)

2个潜在问题。

1 - 比较

// Fields set with non-malloc'ed memory
e.type = type;
e.value = "";
// Fields set with malloc'ed memory
st->entries[pos].type = (char *)calloc(strlen(entry.type)+1, sizeof(char));
st->entries[pos].value = (char *)calloc(strlen(entry.value)+1, sizeof(char));
strcpy(st->entries[pos].type, entry.type);
strcpy(st->entries[pos].value, entry.value);

这两个字段都将字段设置为有效内存,在第二种情况下,动态填充内存。关注的是随后的使用。 OP如何知道free()realloc()第二种而不是第一种。进一步关注:使用registerID(char* type)时,我们如何知道传递给type的值在以后通过字段type使用该指针时仍然有效。建议:

e.type = strdup(type); // or the usual strlen()+1, malloc() and copy
e.value = strdup("");

2 - 未显示yyleng的类型和设置。与strlen(e.name)等相比,它可能不够大?

[编辑]审核后,我认为e.type = type;是问题所在。 e.type需要自己的type

副本

轻微:考虑

// st->entries[pos].type = (char *)calloc(strlen(entry.type)+1, sizeof(char));
// strcpy(st->entries[pos].type, entry.type);
size_t Length = strlen(entry.type) + 1;
st->entries[pos].type = malloc(Length);
memcpy(st->entries[pos].type, entry.type, Length);