C 更改结构字符串
我用莱克斯来实现一个扫描器。我想在解析时构建一个符号表。我有两个结构,SymbolEntry和SymbolTable(如下)。大多数时候,当我调用我的函数来插入一个符号(registerID,也在下面)时,我拥有该条目的所有信息。然而,当我有一个常数时,我也希望得到它的值,但是当我第一次创建条目时,这不是立即可用的。当我稍后在代码中尝试更改entries值时,我正在使该条目使用的整个内存块无效,并且名称和值是打印垃圾 以下是两个结构:C 更改结构字符串,c,struct,segmentation-fault,lex,c-strings,C,Struct,Segmentation Fault,Lex,C Strings,我用莱克斯来实现一个扫描器。我想在解析时构建一个符号表。我有两个结构,SymbolEntry和SymbolTable(如下)。大多数时候,当我调用我的函数来插入一个符号(registerID,也在下面)时,我拥有该条目的所有信息。然而,当我有一个常数时,我也希望得到它的值,但是当我第一次创建条目时,这不是立即可用的。当我稍后在代码中尝试更改entries值时,我正在使该条目使用的整个内存块无效,并且名称和值是打印垃圾 以下是两个结构: typedef struct{ char* type
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;
}
这是插入符号的相关代码(SymbolTable*st,SymbolEntry)<插入时,code>pos始终是数组中的最后一个元素(否则条目不是唯一的,只返回pos
)
稍后,在lex框架匹配紧跟在常量名称后面的值之后,将执行此代码(直接在{number}
的规则中)
为什么这会使数组中此位置的符号项无效,如何安全地更改值的内容
编辑:
这不仅仅发生在常数上。前两个SymbolEntry
s始终是垃圾。我想这可能意味着它们都是,但其他的只是没有被覆盖
此外,对registerID
的后续调用似乎导致数据损坏。只有9个符号,只有前两个是垃圾,34个是前7个。在没有变量的情况下添加更多文本进行解析不会导致任何问题
已解决
事实证明,我只是不小心删除了一行代码,这就是导致错误的原因。我不小心删除了对initSymbolTable
的调用。感谢chux问我如何初始化表。很抱歉。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怎么知道第二种而不是第一种呢。进一步关注:对于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);
您如何分配st->entries[pos]?一种可能是您正在写入分配的内存。我开始将其大小设置为16,但如果曾经size==capacity
,则我会重新分配两倍的大小。每次插入操作后都会执行此检查。此外,我尝试将SymbolEntry数组分配到1024,但仍然无效。我假设这只是一个输入错误,但只是以防万一:您在代码中调用insertSymbol(),但稍后引用insertSymbolTable()。啊,是的,这是一个输入错误。谢谢。我已将所有作业更改为strdup()
callsyyleng
由lex定义,是yytext
的长度。每个记录中的每个字段只创建一次,但type==CONSTANT
的value
除外。然后它只在两个特定位置中的一个发生变化。此时(即使输入文件中没有常量),前3/32个SYMBOL条目已损坏。如果在每一步都使用strdup()
,我看不出这是怎么回事。最糟糕的情况是,我应该处理内存溢出。Hmmm。对于调试目的,请考虑<代码> E.Nord= StrudUp(yyType)< /C>和 Tab.条目[PRYSPYM] . value = StrudUp(YyTr原文)——也许您已经做好了准备。如果这不能解决问题,则问题必须在未发布的代码中。@Jaws212如何分配st
的内存?有一个全局变量SymbolTable表
。它的引用在registerID中的inputSymbol(&table,e)
中传递。我不确定您要我如何处理strdup(yytext)
语句,但我已将所有st->entries[pos].**=strdup(***)
更改为使用文字字符串,问题仍然存在。您在表中输入了什么值。entries
或st->entries
?(注意:不是您在st->entries[pos]…
中输入的值)
e.type = strdup(type); // or the usual strlen()+1, malloc() and copy
e.value = strdup("");
// 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);