如何避免内存同一位置重复写入?C语言词法扫描器问题
解决C语言词法扫描器Lexeme指向同一内存的问题
问题根源
你当前的实现中,所有Token的lexeme都指向同一块动态分配的内存区域,每次循环都会覆盖这块内存的内容,最终所有Token的lexeme自然都指向最后一次写入的字符。而直接使用&scanner->source[scanner->column]会得到从该位置开始的完整字符串(因为C字符串以'\0'结尾),不符合单字符lexeme的需求。
解决方案
1. 为每个Token的Lexeme单独分配内存
针对单字符场景,每次识别字符时,为当前Token的lexeme分配独立内存并复制字符内容:
// 假设token是已初始化的Token结构体指针 token->lexeme = malloc(2); // 1字节存字符,1字节存终止符'\0' if (token->lexeme == NULL) { // 处理内存分配失败,比如返回错误或终止程序 fprintf(stderr, "Memory allocation failed\n"); exit(EXIT_FAILURE); } token->lexeme[0] = scanner->source[scanner->column]; token->lexeme[1] = '\0';
这样每个Token的lexeme都拥有独立的内存空间,后续循环的写入操作不会覆盖之前的内容。
2. 兼容多字符Lexeme的扩展方案
要支持关键字(如var、return)或标识符这类多字符lexeme,只需调整为记录起始位置→扫描结束位置→分配对应内存→复制子串的逻辑:
// 记录lexeme的起始列号 int start_col = scanner->column; // 扫描直到lexeme结束(示例:匹配字母数字组成的标识符/关键字) while (isalnum((unsigned char)scanner->source[scanner->column])) { scanner->column++; } // 计算lexeme长度并分配内存 int lexeme_len = scanner->column - start_col; token->lexeme = malloc(lexeme_len + 1); if (token->lexeme == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(EXIT_FAILURE); } // 复制子串并添加终止符 strncpy(token->lexeme, &scanner->source[start_col], lexeme_len); token->lexeme[lexeme_len] = '\0';
这个逻辑可以统一处理单字符和多字符lexeme,无需单独分支判断。
3. 内存管理注意事项
所有通过malloc分配的lexeme内存,在Token不再使用时必须逐个调用free(token->lexeme)释放,避免内存泄漏。如果你的扫描器会生成大量Token,可以考虑实现一个Token池或统一的内存回收机制,但对于小型扫描器,逐个释放已经足够。
内容的提问来源于stack exchange,提问作者AlphabetsAlphabets
相关产品推荐
相关产品推荐

