bug记录
1 |
stm32f103
错误现象:不使用 freertos 时,可以完成外设初始化,可以完成点灯,串口发送数据。使用 freertos 时,即使把外设初始化函数放到 main 函数最前面,然后立刻点灯,串口发数据,都看不到效果。使用 freertos 时,但删除掉 xTaskCreate 函数(包含heap初始化代码)后,可以点灯,收到数据。
错误原因:在使用 freertos 操作系统时,如果开启了动态创建任务,需要加入内存管理文件(我的是 heap_4.c ),需要定义一个数组供其使用
1
2
3
4
5
6static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
/*config.h*/
//系统所有总的堆大小
//这里被设置成了5k,需要注意的是,虽然sram容量大于10k,但如果设为10k没法运行
//sram大小好像是20k需要注意的是,对应不同芯片,配置的值不同,我的有块 f103 芯片可以配置为 10k,而有块只能配置为 5k。编译完成后,可以在map文件中查看 rw zi 数据所占大小:
1
2
3Total RO Size (Code + RO Data) 11540 ( 11.27kB)
Total RW Size (RW Data + ZI Data) 10232 ( 9.99kB)
Total ROM Size (Code + RO Data + RW Data) 11712 ( 11.44kB)错误现象:外设能够初始化,freertos能创建任务,部分任务能正常运行,某个任务在打印数据时卡死了,QUEUE_Test_Recv_Task发送到字母R时卡死,系统停止调度。
1
2
3
4
5
6
7
8Start creating tasks
Create test queue succeeded.
Create led task succeeded.
Create usart task succeeded.
Create QUEUE_Test_Send_Task succeeded.
Create QUEUE_Test_Recv_Task succeeded.
USART is running!
[QUEUE_Test_R错误原因:该任务的任务栈太小,没法完全容纳要打印的字符串,打印时便出错,将该任务栈适当增大后就可以正常运行了。
错误现象:gpio配置为输入时电平不稳定,哪怕使用上拉,下拉也是,不接杜邦线时稳定,接上杜邦线就不稳定了
解决方法:换块板子,有块stm32f103c6t6的板子有以上问题,换上c8t6这个问题就解决了
错误现象:gpio配置为输入时检测不到输入电平,检测配置,毫无问题,相邻的几个引脚也没问题。
错误原因:排针和板子的该引脚没焊上。。。
错误现象:串口显示错误信息
Error:..\freertos\port\port.c,680
查看原文如下:1
2
3
4
5
6
7
8
9/* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY.
.....................
*/
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );错误原因:大致就是说,要求使用到了 在中断调用了 freertos 安全api接口的中断,必须位于freertos可管理中断优先级之下。将中断优先级改到可管理的优先级之下就行了。
检查错误时,还注意到了696行
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
按理说应该报错的,因为它括号里的判断为假,但是它右边的值不是常量,是个变量,可能在运行中更改的。这点在检查bug中需要注意,不要 点一下 “ go to definition” 发现是 0 就以为它一直是 0 了。
C语言
错误现象:fsanitize报错,显示如下:
1
2
3
4
5
6
7AddressSanitizer:DEADLYSIGNAL
=================================================================
==739==ERROR: AddressSanitizer: SEGV on unknown address 0x00000000000f (pc 0x5625e6140822 bp 0x7ffce9918610
sp 0x7ffce9918050 T0)
==739==The signal is caused by a READ memory access.
==739==Hint: address points to the zero page.
AddressSanitizer:DEADLYSIGNAL错误原因:很可能是使用了未初始化的指针。这里报错是因为使用了文件描述符,但没有为其赋值,然后在使用 fclose 关闭它时报错。
1
2FILE * fp_res = NULL;//文件指针
//fclose(fp_res);错误现象:fsanitize报错,不加
-fsanitize=address
不报错,显示如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45=================================================================
==1301==ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address 0x7fffca3868a4 at pc 0x564b815e8c89 bp 0x7fffca386850 sp 0x7fffca386840
WRITE of size 4 at 0x7fffca3868a4 thread T0
#0 0x564b815e8c88 in main (/mnt/d/stm32/flower/stm32-project/a_Server/t+0x2c88)
#1 0x7fb02027e082 in __libc_start_main ../csu/libc-start.c:308
#2 0x564b815e860d in _start (/mnt/d/stm32/flower/stm32-project/a_Server/t+0x260d)
Address 0x7fffca3868a4 is located in stack of thread T0
SUMMARY: AddressSanitizer: dynamic-stack-buffer-overflow (/mnt/d/stm32/flower/stm32-project/a_Server/t+0x2c88) in main
Shadow bytes around the buggy address:
0x100079468cc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100079468cd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100079468ce0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100079468cf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100079468d00: 00 00 00 00 00 00 00 00 00 00 00 00 ca ca ca ca
=>0x100079468d10: 00 00 00 00[04]cb cb cb cb cb cb cb 00 00 00 00
0x100079468d20: 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00
0x100079468d30: f2 f2 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100079468d40: 00 00 00 00 00 f2 f2 f2 f2 f2 f2 f2 f2 f2 00 00
0x100079468d50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100079468d60: 00 f2 f2 f2 f2 f2 f2 f2 f2 f2 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
#0 0x564b815e8c88 in main (/mnt/d/stm32/flower/stm32-project/a_Server/t+0x2c88)
==1301==ABORTING
#1 0x7fb02027e082 in __libc_start_main ../csu/libc-start.c:308
#2 0x564b815e860d in _start (/mnt/d/stm32/flower/stm32-project/a_Server/t+0x260d)错误原因:局部变量和数组没有正确的分配空间,导致写入了栈空间之外的内存。代码中有如下几段语句:
1
2
3
4pid_t pid[atoi(argv[3])];
*** 省略若干行 ***
while(i <= atoi(argv[3])){
pid[i] = fork();查明后,发现原因很简单,容易想到(甚至 chatGPT都给了明确的建议,如下),但找到这个错误过程还是挺长的。
- 递归调用没有正确的停止条件。
- 局部变量和数组没有正确的分配空间,导致写入了栈空间之外的内存。
- 指针未进行正确的内存管理,例如指向了已释放的内存、未初始化的指针或者越界访问了指针指向的内存。
debug过程:
第一,通过给出的偏移地址(t+0x2c88)查看反汇编(objdump -t xxx),但似乎地址没找对,也不太清除具体该汇编语句是什么含义:
1
2
3
42c81: 48 89 c7 mov %rax,%rdi
2c84: e8 77 f7 ff ff callq 2400 <__asan_report_store4@plt>
2c89: 48 8b 85 08 fc ff ff mov -0x3f8(%rbp),%rax
2c90: 8b 95 f0 fb ff ff mov -0x410(%rbp),%edx通过上下文,基本可以将该语句锁定在while循环内,但不知道对应那条c语言语句。
第二,查看影子寄存器,待研究
第三,gdb调试,下面详述一下调试过程,
先输入
gdb xxx
, 然后设置参数set args arg1 arg2 arg3
,打断点break 函数名/行号
,然后run
开始运行, 然后输入next
,一行一行调试。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20ttj@ttj /m/d/s/f/s/a_Server (master)> gdb t
Reading symbols from t...
(gdb) set args 172.27.2.164 7788 9
(gdb) b 85
Breakpoint 1 at 0x2c30: file virtual_terminal.c, line 85.
(gdb) r
Starting program: /mnt/d/stm32/flower/stm32-project/a_Server/t 172.27.2.164 7788 9
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, main (argc=4, argv=0x7fffffffe3e8) at virtual_terminal.c:85
85 while(i <= atoi(argv[3])){
(gdb) n
86 pid[i] = fork();
(gdb) n
[Detaching after fork from child process 2936]
[pid](2936) stu_cli_res_pid_is_2936.txt is created!
87 if(pid[i] == -1){
(gdb) n
92 else if(pid[i] == 0){最后会有一个报错,这里就直接把行号写出来了,86行,到这才发现是这个数组越界了。
1
2
3
4
5
6
7
8
9
10[Detaching after fork from child process 2952]
=================================================================
==2952==ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address 0x7fffffffde44 at pc 0x555555556c89 bp 0x7fffffffddf0 sp 0x7fffffffdde0
WRITE of size 4 at 0x7fffffffde44 thread T0
=================================================================
==2932==ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address 0x7fffffffde44 at pc 0x555555556c89 bp 0x7fffffffddf0 sp 0x7fffffffdde0
WRITE of size 4 at 0x7fffffffde44 thread T0
#0 0x555555556c88 in main /mnt/d/stm32/flower/stm32-project/a_Server/virtual_terminal.c:86
#1 0x7ffff73c2082 in __libc_start_main ../csu/libc-start.c:308
#2 0x55555555660d in _start (/mnt/d/stm32/flower/stm32-project/a_Server/t+0x260d)错误现象:此错误未知,用sscanf很难读取数据,一直没法读取下一个数据,只有用snprintf才成功。下次试试
volatile
?1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24if(sscanf(read_buf, "%d", &user_num) == 1){
regroup[regroup_index][i++] = user_num;
}
while(*(read_buf+si) <= '9' && *(read_buf+si) >= '0') si++;
char *p = strchr(read_buf, ' ');
while(1){
int flag = sscanf(p+si, "%d", &user_num);
//while(*(read_buf+si) <= '9' && *(read_buf+si) >= '0') si++;
si += snprintf(NULL, 0, "%d", user_num); // 加上这一行
if(flag == 1) {
printf("p: %s; si : %d\n", p, si);
regroup[regroup_index][i++] = user_num;
}
else{
break;
}
//p = strchr(p, ' ');
/*while(*read_buf != 0){
*read_buf = 0;
read_buf++;
}
printf("user_num: %d; %s\n", user_num, p);
*/
}
imx6ull
相关使用可以查看《imx6ull使用》
错误现象:
1
2
3
4
5
6
7//申明:
void rtc_setdatetime(struct rtcdatetime *datetime);
//定义:
void rtc_setdatetime(struct rtcdatetime *datetime){xxx}
//报错如下:
declaration is incompatible with "void rtc_setdatetime(struct rtcdatetime *datetime)" (declared at line 27 of "/home/vmttj/linux_src/ttj_imx6ull/Board_Drivers/16_rtc/bsp/rtc/bsp_rtc.h")
declaration is incompatible with "void rtc_setdatetime(struct rtcdatetime *datetime)" (declared at line 39 of "/home/vmttj/linux_src/ttj_imx6ull/Board_Drivers/16_rtc/bsp/rtc/bsp_rtc.c")错误原因:结构体写错了,正确的写法是
struct rtc_datetime
,改过来就正确了,但为什么报错不兼容还不清楚。https://blog.csdn.net/ReadAir/article/details/90439479
python
错误现象:
1
2
3
4
5
6
7
8
9
10
11
12
13
14源代码:
for l in range(1, L):
### START CODE HERE ### (≈ 2 lines of code)
parameters['W' + str(l)] = np.random.randn(layer_dims[l], layer_dims[l - 1]) * 0.01
parameters['b' + str(l)] = np.zeros((layer_dims[l], 1)
### END CODE HERE ###
assert(parameters['W' + str(l)].shape == (layer_dims[l], layer_dims[l-1]))
assert(parameters['b' + str(l)].shape == (layer_dims[l], 1))
报错:
Cell In[32], line 24
assert(parameters['W' + str(l)].shape == (layer_dims[l], layer_dims[l-1]))
^
SyntaxError: invalid syntax错误原因,上一行结尾少了一个右括号。
错误现象
1 | 代码: |
错误原因:使用一次backward后,会自动删除中间结果(计算图),导致第二次使用时出错,(ps.看一篇文章说计算过程带加号就不会删除)。可以在backward函数中加上参数retain_graph=True
来保留计算图。
- linux按照qt后无法打开,报如下错误(使用 export QT_DEBUG_PLUGINS=1显示错误信息):
1 | Cannot load library /opt/Qt5.12.10/Tools/QtCreator/lib/Qt/plugins/platforms/libqxcb.so: (libxcb- |
重点在这一行:libxcb-render-util.so.0: cannot open shared object file: No such file or directory
,找不到这个库,下载安装即可,其对应的库名为libxcb-render-util0
(都是类似的),更改后重新启动qt,有新的报错继续更改即可。
plus. 使用命令查看libqxcb依赖关系: ldd /opt/Qt5.12.10/Tools/QtCreator/lib/Qt/plugins/platforms/ libqxcb.so
,结果如下:
1 | ...... |
表示缺少这个包。
- 在Qt中使用Python时报错,include了一个 <pybind11/embed.h>文件
1 | //object.h |
这里是python中的object文件,不应该是这个头文件出错了,而是头文件里面冲突了,在Qt中,slots是特殊的宏,define slots __attribute__((annotate("qt_slot")))
它被用来声明函数是槽函数,当qt的头文件在<pybind11/embed.h>之前时,后者的slots变量就被替换成了qt中的宏,导致分号前没有变量名字而报错。
解决方法:将<pybind11/embed.h>这个头文件放到Qt的头文件之前。
参考:https://github.com/pybind/pybind11/issues/2305#issuecomment-660540709
pthread_create陷阱
首先看一下该函数的函数原型。
1 | 1#include <pthread.h> |
函数原型中的第三个参数,为函数指针,指向处理线程函数的地址。该函数,要求为静态函数。如果处理线程函数为类成员函数时,需要将其设置为静态成员函数。
this指针的锅
pthread_create的函数原型中第三个参数的类型为函数指针,指向的线程处理函数参数类型为(void *)
,若线程函数为类成员函数,则this指针会作为默认的参数被传进函数中,从而和线程函数参数(void*)
不能匹配,不能通过编译。
静态成员函数就没有这个问题,里面没有this指针。
一般解决方法就是第三个参数传入一个静态函数,第四个参数传入一个对象,在静态函数中完成对对象中成员函数的调用。
找不到函数定义
- 虽然可以点击函数名字跳转,但就是会报错,找不到函数定义,可能是因为头文件和系统的文件重名了。
- 可能是cmake配置,或makefile配置没有编译某些文件,导致了这个问题。但是vsc编辑器可以帮我们进行跳转
size()
如下的代码:size()其实返回的是unsigned,如果size为0,减一后为超级大的数,导致出错。
1 | for(int i = 0; i < ret.size() - 1; i++){ |