FreeRTOS头文件引用顺序问题

今天在调ESPIDF时候遇到一个非常奇怪的问题。最后发现是关于FreeRTOS头文件的引用顺序导致的。困扰了好几个小时,这里记录。

问题描述

今天在写ESP32IDF工程时,发现自己的头文件引用一直有问题,具体表现为交换两个头文件引用顺序会导致出现一大堆报错:

1
2
3
4
//错误的引用顺序
#include "my_event.h"
#include "lvgl_port.h"

  • my_event.h
1
2
3
4
5
6
7
8
9
10
11
12
#ifndef _MY_EVENT_H
#define _MY_EVENT_H
#include "freertos/semphr.h"//信号量
#include "freertos/FreeRTOS.h"

#include "freertos/task.h"


extern SemaphoreHandle_t xGuiSemaphore;//GUI信号量防止多线程操作GUI


#endif
  • lvgl_port.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef _LVGL_PORT_H
#define _LVGL_PORT_H

......

#define LVGL_TICK_PERIOD_MS 2

#include "freertos/FreeRTOS.h"

#include "esp_lcd_panel_io.h" //IO口和电平定义设置
#include "hx8369.h"//hx8369面板的创建

......


#endif //_LVGL_PORT_H

以这样的顺序引用会导致疯狂的报错:

image-20230526015529416

6,直接蒙了。

结果是,工程里到处都是红标,完全无法定位错误在哪里。

问题解决

经过我一点一点加改头文件,终于发现把那两个头文件引用顺序换一下就可以编译了(?????什么玄学解决方法,我不服啊)

经过再深入查看所有引用的头文件,终于定位了问题:

  • FreeRTOS.h
1
2
3
4
5
#ifndef INC_FREERTOS_H
#define INC_FREERTOS_H
.....

#endif
  • semphr.h
1
2
3
#ifndef INC_FREERTOS_H
#error "include FreeRTOS.h" must appear in source files before "include semphr.h"
#endif

这个#error直接导致sempher.h必须要在FreeRTOS.h之后引用。

对于上面的问题,是因为在lvgl_port.h中已经包含了FreeRTOS.h所以能让后面不报错

这个ERROR直接淹没在报错的汪洋大海中,根本定位不到!!!

所以只要注意,使用FreeRTOS其他组件时,头文件必须在

FreeRTOS.h后引用。

后续

为了弄明白为什么会有如此奇怪的设计,头文件都要按依赖顺序来引用,而不是顺便引用或者自动include依赖的头文件,我到官网找了一下发现如下回答

It is to make it more obvious what is going on - I have a personal preference not to include one header file from inside another because you can get yourself tied up on knots - but besides my preference formal coding standards (such as those for safety or security certifications) normally forbid nesting headers. In FreeRTOS there is one place where it can’t be avoided because you have to get the configuration file, portable header, and then the checks to see which configuration items are left undefined, all in the correct order.

原来是大佬的洁癖啊。

现在凌晨2点了,害。