ESP32服务器处理JSON载荷POST请求及cJSON解析内核panic问题咨询
核心问题定位
你遇到的panic本质是传入cJSON解析的内容根本不是JSON格式,具体原因如下:
- 你设置的表单
enctype为text/plain,提交后服务端收到的POST payload格式是key1=value1 key2=value2,完全不符合JSON的语法规范(JSON要求键值对用双引号包裹、用大括号包裹结构,键值对之间用逗号分隔) cJSON_Parse解析非法格式的输入时会直接返回NULL,你没有对root是否为NULL做校验,后续直接把空指针传入cJSON_GetObjectItemCaseSensitive,得到的typeJSON也是空指针- 后续你直接访问空指针
typeJSON的成员valuestring,就触发了LoadProhibited类型的内存访问错误panic
解决方案
方案1:前端直接提交JSON格式数据(推荐,适配现有cJSON解析逻辑)
修改前端表单的提交逻辑,不要用原生表单默认提交,用JS拦截提交事件,把表单数据组装成JSON后提交:
<form id="fermForm"> <fieldset> <legend>Fermentation:</legend> <input name="type" type="radio" value="Ale" /> Ale <br /> <input checked="checked" name="type" type="radio" value="Lager" /> Lager <br /> <label for="primary-duration">Duration of primary</label><br /> <input name="primary-duration" type="text" value="5" /> <br /> <input type="submit" value="Submit"><br /> </fieldset> </form> <script> document.getElementById('fermForm').addEventListener('submit', function(e) { e.preventDefault(); const formData = new FormData(this); const payload = Object.fromEntries(formData.entries()); fetch('/你的提交接口地址', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); }); </script>
此时服务端收到的payload就是合法JSON:{"type":"Lager","primary-duration":"5"},你的现有cJSON解析逻辑就能正常工作,注意要先加空指针校验,还要记得释放cJSON内存避免泄漏:
cJSON *root = cJSON_Parse(buf); if (root == NULL) { ESP_LOGE(SERVER_HANDLER_TAG, "JSON解析失败,输入格式非法"); return; } const cJSON *typeJSON = cJSON_GetObjectItemCaseSensitive(root, "type"); // 原有逻辑 cJSON_Delete(root);
方案2:后端解析text/plain格式的表单数据(不修改前端)
如果不想改前端,就不要用cJSON解析,直接拆分字符串提取键值对即可:
// buf内容为type=Lager primary-duration=5 char *key = strtok(buf, "= "); char *val; char type[16] = {0}; int primary_duration = 0; while(key != NULL) { val = strtok(NULL, "= "); if (strcmp(key, "type") == 0) { strncpy(type, val, sizeof(type)-1); } else if (strcmp(key, "primary-duration") == 0) { primary_duration = atoi(val); } key = strtok(NULL, "= "); }
内容的提问来源于stack exchange,提问作者vict
相关产品推荐
相关产品推荐

