C语言实现JSON解释器:递增pairsSize触发段错误崩溃
JSON解释器段错误问题排查与代码优化
我正在自行实现一款JSON解释器,但向结构体中添加值时,一旦递增pairsSize变量,程序就会因段错误崩溃。排查代码后发现,在case KEYPAIR_DELIM中取消json->pairsSize++的注释并执行内存重分配时,程序立即崩溃。相关代码如下:
json.c中interpret()函数部分代码
size_t jsonContentLen = strlen(jsonContent); char * placeHolder = malloc(1); unsigned int placeHolderPtr = 0; bool isArray = false; for (size_t i = 0; i < jsonContentLen; i++) { switch(jsonContent[i]) { case KEYPAIR_DELIM: { placeHolder[placeHolderPtr] = '\0'; // 取消`json->pairsSize++`注释后立即触发段错误 json->pairs = realloc(json->pairs, sizeof(struct Pair *) * (json->pairsSize+1)); json->pairs[json->pairsSize] = init_pair(); json->pairs[json->pairsSize]->key = realloc(json->pairs[json->pairsSize]->key, placeHolderPtr+1); strncpy(json->pairs[json->pairsSize]->key, placeHolder, placeHolderPtr+1); printf("%s\n", json->pairs[json->pairsSize]->key); placeHolder[0] = '\0'; placeHolderPtr = 0; } case NEXT_PAIR: { placeHolder[placeHolderPtr] = '\0'; size_t placeHolderLen = strlen(placeHolder); json->pairs[json->pairsSize]->values = realloc(json->pairs[json->pairsSize]->values, sizeof(void *) * (json->pairs[json->pairsSize]->valuesSize+1)); // OMG THIS LOOKS SO BAD AHHHHHHH json->pairs[json->pairsSize]->values[json->pairs[json->pairsSize]->valuesSize] = malloc(placeHolderLen+1); strncpy(json->pairs[json->pairsSize]->values[json->pairs[json->pairsSize]->valuesSize], placeHolder, placeHolderLen+1); printf("%s\n", json->pairs[json->pairsSize]->values[json->pairs[json->pairsSize]->valuesSize]); placeHolder[0] = '\0'; placeHolderPtr = 0; json->pairs[json->pairsSize]->valuesSize++; if (isArray == false) { // 莫名触发段错误,无法排查 //json->pairsSize++; } break; } } }
json.h部分代码
#define DOUBLE_QUOTE '"' #define KEYPAIR_DELIM ':' #define OBJECT_OPEN '{' #define OBJECT_CLOSE '}' #define ARRAY_OPEN '[' #define ARRAY_CLOSE ']' #define NEXT_PAIR ',' struct Pair { char * key; void ** values; unsigned int valuesSize; }; struct JSON { char * objectName; struct Pair ** pairs; unsigned int pairsSize; struct JSON ** objects; unsigned int objectsSize; struct JSON * prev; }; struct JSON * init_json(); struct Pair * init_pair();
问题原因与修复
结构体初始化不完整
- 确保
init_json()中json->pairs初始化为NULL,json->pairsSize初始化为0;init_pair()中values初始化为NULL,valuesSize初始化为0。realloc对野指针操作会直接触发崩溃,未初始化的数组索引也会访问非法内存。
- 确保
case穿透导致越界访问
case KEYPAIR_DELIM代码块末尾缺少break,执行完该case后会直接进入case NEXT_PAIR逻辑。如果此时pairsSize已递增,访问json->pairs[json->pairsSize]->values会越界,直接触发段错误。修复后代码:case KEYPAIR_DELIM: { placeHolder[placeHolderPtr] = '\0'; // 扩容并初始化新Pair json->pairs = realloc(json->pairs, sizeof(struct Pair *) * (json->pairsSize + 1)); json->pairs[json->pairsSize] = init_pair(); // 复制key值 json->pairs[json->pairsSize]->key = realloc(json->pairs[json->pairsSize]->key, placeHolderPtr + 1); strncpy(json->pairs[json->pairsSize]->key, placeHolder, placeHolderPtr + 1); printf("%s\n", json->pairs[json->pairsSize]->key); // 最后递增计数 json->pairsSize++; placeHolder[0] = '\0'; placeHolderPtr = 0; break; // 新增break避免case穿透 }
placeHolder内存溢出
- 初始
placeHolder仅分配1字节空间,后续写入数据会越界破坏堆内存。改为动态扩容:// 替换原placeHolder初始化 size_t placeHolderCap = 16; char * placeHolder = malloc(placeHolderCap); // 在每次写入placeHolder前检查空间 if (placeHolderPtr >= placeHolderCap) { placeHolderCap *= 2; placeHolder = realloc(placeHolder, placeHolderCap); } placeHolder[placeHolderPtr++] = jsonContent[i];
- 初始
代码可读性优化
使用临时指针减少多层嵌套的指针访问,简化代码:
// 在NEXT_PAIR的case中替换原有逻辑 struct Pair *currentPair = json->pairs[json->pairsSize - 1]; size_t newValuesSize = currentPair->valuesSize + 1; currentPair->values = realloc(currentPair->values, sizeof(void *) * newValuesSize); currentPair->values[currentPair->valuesSize] = malloc(placeHolderLen + 1); strncpy(currentPair->values[currentPair->valuesSize], placeHolder, placeHolderLen + 1); printf("%s\n", currentPair->values[currentPair->valuesSize]); currentPair->valuesSize = newValuesSize;
内容的提问来源于stack exchange,提问作者ThatPrimitive_Remastered
相关产品推荐
相关产品推荐

