C语言词法分析器运行输出随机字符问题求助
C语言词法分析器出现随机垃圾字符问题
问题背景
我正在用C语言编写一个词法分析器,预期功能如下:
输入:2 + 3
输出:
Token text (Operand): 2 Token text: + Token lexical Category: ADD Token text (Operand): 3
对应的代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> void token(char c); int main(int argc, char *argv[]){ if(argc == 1){ printf("[*] Usage ./%s <TextToAnalyze>\n", argv[0]); //用户输入的参数将被分析 } else{ char arguments[argc]; for(int i = 1; i < argc; i++){ strcat(arguments, argv[i]);//参数将被复制并分隔到变量"arguments" strcat(arguments, " "); } for( int i = 0; i < strlen(arguments); ++i){ token(arguments[i]); //遍历输入元素,用token函数分析 } } return 0; } void token(char c){ if(isdigit(c)){ printf("Token text (OPERAND): %c\n", c); } else if(isalpha(c)){ printf("Token text: %c\n", c); printf("Token lexical category: CHARACTER\n"); } else if(isspace(c)){ asm ("nop"); } else { switch(c){ case '+': printf("Token text: %c\n", c); printf("Token lexical category: ADD\n"); break; case '-': printf("Token text: %c\n", c); printf("Token lexical category: SUBTRACT\n"); break; case '*': printf("Token text: %c\n", c); printf("Token lexical category: MULTIPLY\n"); break; case '/': printf("Token text: %c\n", c); printf("Token lexical category: DIVIDE\n"); break; case '%': printf("Token text: %c\n", c); printf("Token lexical category: MODULE\n"); break; case '<': printf("Token text: %c\n", c); printf("Token lexical category: LESS THAN\n"); break; case '>': printf("Token text: %c\n", c); printf("Token lexical category: GREATER THAN\n"); break; case '=': printf("Token text: %c\n", c); printf("Token lexical category: EQUAL\n"); break; default: printf("Operator not found: %c \n", c); } } }
错误现象
运行程序输入- 2时,终端输出随机垃圾字符:
bash-3.2$ ./a.out - 2 Operator not found: Token text: Y Token lexical category: CHARACTER Operator not found: ? Operator not found: ? Operator not found: ? Operator not found: Token text: - Token lexical category: SUBTRACT Token text (OPERAND): 2 bash-3.2$
问题原因
- 未初始化数组引发垃圾数据读取:
char arguments[argc];定义的数组未初始化,内存中残留随机垃圾值。而strcat要求目标字符串必须以'\0'结尾,否则会从内存随机位置读取直到找到'\0',导致垃圾字符被当作有效内容处理。 - 数组空间不足导致内存越界:
argc是命令行参数的个数,并非所有参数的总字符长度。比如输入- 2时argc=3,数组大小仅为3,但实际需要存储"- 2\0"共4个字符,空间不足触发内存越界,引发未定义行为。
修复方案
方案1:静态数组(计算足够空间并初始化)
先计算所有参数的总长度,加上参数间空格的数量,再预留字符串结束符的空间,同时初始化数组为空字符串:
int main(int argc, char *argv[]){ if(argc == 1){ printf("[*] Usage ./%s <TextToAnalyze>\n", argv[0]); } else{ // 计算总字符长度 int total_len = 0; for(int i = 1; i < argc; i++){ total_len += strlen(argv[i]); } // 添加参数间的空格(argc-1个参数对应argc-2个空格) total_len += (argc - 2); // 定义数组并预留结束符空间 char arguments[total_len + 1]; // 初始化为空字符串 arguments[0] = '\0'; for(int i = 1; i < argc; i++){ strcat(arguments, argv[i]); // 最后一个参数后不加空格 if(i != argc - 1){ strcat(arguments, " "); } } for( int i = 0; i < strlen(arguments); ++i){ token(arguments[i]); } } return 0; }
方案2:动态内存分配(适合长参数场景)
如果担心栈空间不足,使用malloc动态分配内存,使用后记得释放:
int main(int argc, char *argv[]){ if(argc == 1){ printf("[*] Usage ./%s <TextToAnalyze>\n", argv[0]); } else{ int total_len = 0; for(int i = 1; i < argc; i++){ total_len += strlen(argv[i]); } total_len += (argc - 2); // 动态分配内存,检查分配是否成功 char *arguments = malloc(total_len + 1); if(arguments == NULL){ perror("malloc failed"); return 1; } arguments[0] = '\0'; for(int i = 1; i < argc; i++){ strcat(arguments, argv[i]); if(i != argc - 1){ strcat(arguments, " "); } } for( int i = 0; i < strlen(arguments); ++i){ token(arguments[i]); } // 释放动态分配的内存 free(arguments); } return 0; }
另外,原代码中asm ("nop");可替换为return;或直接空块,提升代码可读性。
内容的提问来源于stack exchange,提问作者AndresTheGiant-
相关产品推荐
相关产品推荐

