Matrix

CarlyleLiu‘s Blog

采样点

在基尔霍夫定律下,三相电流的合应该等于 0,因此只需要获取亮相电流就可以重构出完整的三相电流。

对于 STM32 一般通过高级定时器的 channel4 作为 ADC 的触发源,对于下桥臂电流采样,需要在下桥臂 MOS 管导筒的时候才能去采样,而且需要在 MOS 管导通时间以及电流稳定后才能采样到比较可靠的电流。

阅读全文 »

差速轮运动学模型

机器人坐标系下的变换

运动特性为两轮差速驱动,其底部后方两个同构驱动轮的转动为其提供动力,前方的随动轮起支撑作用并不推动其运动,如下图两轮差速驱动示意图所示。

机器人的运动简化模型如图 4-1 所示,X 轴正方向为前进、Y 轴正方向为左平移、Z 轴正方向为逆时针。机器人两个轮子之间的间距为 D,机器人 X 轴和 Z 轴的速度分别为:\(V_x\)\(V_z\) ,机器人左轮和右轮的速度分别为:\(V_l\)\(V_r\)

假设机器人往一个左前的方向行进了一段距离,设机器人的右轮比左轮多走的距离近似为 K, 以机器人的轮子上的点作为参考点做延长参考线,可得:\(θ_1 = θ_2\) 。由于这个\(Δ_t\) 很小,因此角度的变化量\(θ_1\) 也很小,因此有近似公式:

阅读全文 »

Valgrind 的介绍

Valgrind 可以用来检测程序是否有非法使用内存的问题,例如访问未初始化的内存、访问数组时越界、忘记释放动态内存等问题。在 Linux 可以使用下面的命令安装 Valgrind:

1
2
3
4
5
6
$ wget ftp://sourceware.org/pub/valgrind/valgrind-3.13.0.tar.bz2
$ bzip2 -d valgrind-3.13.0.tar.bz2
$ tar -xf valgrind-3.13.0.tar
$ cd valgrind-3.13.0
$ ./configure && make
$ sudo make install

检测内存泄漏

C 语言

Valgrind 可以用来检测程序在哪个位置发生内存泄漏,例如下面的程序:

1
2
3
4
5
6
#include <stdlib.h>
int main()
{
int *array = malloc(sizeof(int));
return 0;
}

编译程序时,需要加上-g 选项:

1
$ gcc -g -o main_c main.c

使用 Valgrind 检测内存使用情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ valgrind --tool=memcheck --leak-check=full  ./main_c
==31416== Memcheck, a memory error detector
==31416== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==31416== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==31416== Command: ./main_c
==31416==
==31416== HEAP SUMMARY:
==31416== in use at exit: 4 bytes in 1 blocks
==31416== total heap usage: 1 allocs, 0 frees, 4 bytes allocated
==31416==
==31416== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==31416== at 0x4C2DBF6: malloc (vg_replace_malloc.c:299)
==31416== by 0x400537: main (main.c:5)
==31416==
==31416== LEAK SUMMARY:
==31416== definitely lost: 4 bytes in 1 blocks
==31416== indirectly lost: 0 bytes in 0 blocks
==31416== possibly lost: 0 bytes in 0 blocks
==31416== still reachable: 0 bytes in 0 blocks
==31416== suppressed: 0 bytes in 0 blocks
==31416==
==31416== For counts of detected and suppressed errors, rerun with: -v
==31416== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

先看看输出信息中的 HEAP SUMMARY,它表示程序在堆上分配内存的情况,其中的 1 allocs 表示程序分配了 1 次内存,0 frees 表示程序释放了 0 次内存,4 bytes allocated 表示分配了 4 个字节的内存。 另外,Valgrind 也会报告程序是在哪个位置发生内存泄漏。例如,从下面的信息可以看到,程序发生了一次内存泄漏,位置是 main.c 文件的第 5 行:

1
2
3
==31416== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==31416== at 0x4C2DBF6: malloc (vg_replace_malloc.c:299)
==31416== by 0x400537: main (main.c:5)

C++语言

Valgrind 也可以用来检测 C++ 程序的内存泄漏,下面是一个正常的 C++ 程序,没有发生内存泄漏:

1
2
3
4
5
6
7
#include <string>
int main()
{
auto ptr = new std::string("Hello, World!");
delete ptr;
return 0;
}

使用 Valgrind 分析这段程序:

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
$ valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all ./main_cpp
==31438== Memcheck, a memory error detector
==31438== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==31438== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==31438== Command: ./main_cpp
==31438==
==31438== HEAP SUMMARY:
==31438== in use at exit: 72,704 bytes in 1 blocks
==31438== total heap usage: 2 allocs, 1 frees, 72,736 bytes allocated
==31438==
==31438== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1
==31438== at 0x4C2DBF6: malloc (vg_replace_malloc.c:299)
==31438== by 0x4EC3EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==31438== by 0x40104E9: call_init.part.0 (dl-init.c:72)
==31438== by 0x40105FA: call_init (dl-init.c:30)
==31438== by 0x40105FA: _dl_init (dl-init.c:120)
==31438== by 0x4000CF9: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so)
==31438==
==31438== LEAK SUMMARY:
==31438== definitely lost: 0 bytes in 0 blocks
==31438== indirectly lost: 0 bytes in 0 blocks
==31438== possibly lost: 0 bytes in 0 blocks
==31438== still reachable: 72,704 bytes in 1 blocks
==31438== suppressed: 0 bytes in 0 blocks
==31438==
==31438== For counts of detected and suppressed errors, rerun with: -v
==31438== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

使用 Valgrind 分析 C++ 程序时,有一些问题需要留意。例如,这个程序并没有发生内存泄漏,但是从 HEAP SUMMARY 可以看到,程序分配了 2 次内存,但却只释放了 1 次内存,为什么会这样呢?

实际上这是由于 C++ 在分配内存时,为了提高效率,使用了它自己的内存池。当程序终止时,内存池的内存才会被操作系统回收,所以 Valgrind 会将这部分内存报告为 reachable 的,需要注意,reachable 的内存不代表内存泄漏,例如,从上面的输出中可以看到,有 72704 个字节是 reachable 的,但没有报告内存泄漏。

检测越界访问

C++ 程序经常出现的 Bug 就是数组越界访问,例如下面的程序出现了越界访问:

1
2
3
4
5
6
7
8
#include <vector>
#include <iostream>
int main()
{
std::vector<int> v(10, 0);
std::cout << v[10] << std::endl;
return 0;
}

使用 Valgrind 分析这段程序,Valgrind 会提示越界访问:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ g++ -std=c++11 -g -o main_cpp main.cpp
$ valgrind --tool=memcheck --leak-check=full ./main_cpp
==31523== Memcheck, a memory error detector
==31523== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==31523== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==31523== Command: ./main_cpp
==31523==
==31523== Invalid read of size 4
==31523== at 0x400AD7: main (main.cpp:7)
==31523== Address 0x5ab5ca8 is 0 bytes after a block of size 40 alloc'd
==31523== at 0x4C2E216: operator new(unsigned long) (vg_replace_malloc.c:334)
==31523== by 0x4010D3: __gnu_cxx::new_allocator<int>::allocate(unsigned long, void const*) (new_allocator.h:104)
==31523== by 0x401040: std::allocator_traits<std::allocator<int> >::allocate(std::allocator<int>&, unsigned long) (alloc_traits.h:491)
==31523== by 0x400F91: std::_Vector_base<int, std::allocator<int> >::_M_allocate(unsigned long) (stl_vector.h:170)
==31523== by 0x400E7E: std::_Vector_base<int, std::allocator<int> >::_M_create_storage(unsigned long) (stl_vector.h:185)
==31523== by 0x400D1E: std::_Vector_base<int, std::allocator<int> >::_Vector_base(unsigned long, std::allocator<int> const&) (stl_vector.h:136)
==31523== by 0x400C11: std::vector<int, std::allocator<int> >::vector(unsigned long, int const&, std::allocator<int> const&) (stl_vector.h:291)
==31523== by 0x400AB9: main (main.cpp:6)

Invalid read of size 4 表示越界读取 4 个字节,这个操作出现在 main.cpp 文件的第 7 行。另外可以看到,vector 分配了一块 40 字节的内存,程序越界访问紧急着这块内存之后的 4 个字节。

检测未初始化的内存

另一种经常出现的 Bug,就是程序访问了未初始化的内存。例如:

1
2
3
4
5
6
7
8
9
10
#include <iostream>
int main()
{
int x;
if (x == 0)
{
std::cout << "X is zero" << std::endl;
}
return 0;
}

使用 Valgrind 检测这个程序:

1
2
3
4
5
6
7
8
9
$ g++ -std=c++11 -g -o main_cpp main.cpp
$ valgrind --tool=memcheck --leak-check=full ./main_cpp
==31554== Memcheck, a memory error detector
==31554== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==31554== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==31554== Command: ./main_cpp
==31554==
==31554== Conditional jump or move depends on uninitialised value(s)
==31554== at 0x400852: main (main.cpp:6)

输出中提示了 main.cpp 文件的第 6 行访问了未初始化的内存。

参考文献

https://senlinzhan.github.io/2017/12/31/valgrind/

前言

应用崩溃,各种空指针等大概是应用开发过程中最常遇到的问题了。而我们传统的调试利器 syslog 能快速解决 90%的问题,但是对于那些低概率,需要老化几十小时才能复现到的问题通过 syslog 就很难定位到问题了。这时如果可以提供一种情景再现的方式将应用崩溃现场的调用栈以及栈内数据给展现出来那么对于我们定位问题是大有帮助的。而笔者最近就遇到大量这种(基本都是老化过程中遇到的低概率)问题,于是这里尝试提供一种方法来快速定位问题。当然这类问题都是一个路子,掌握这种分析方法以后遇到这类问题就都可以轻松处理了。

本文提供的一种解决方案是通过 gdb+core dump 文件分析调试方法,具体如下:

阅读全文 »

前言

最近在工作中遇到了一些内存泄露问题,虽然泄露速度很慢,但是对于小型嵌入式设备而言资源本身就很紧张而且过 72h 老化测试过不了。于是寻找一些内存泄露检测工具辅助查找内存泄露问题,此处只使用了 leaktracer 这个开源库来帮助查找内存泄露问题。

阅读全文 »

最近出现了比较多的内核崩溃的问题,之前也曾转发过网上一篇关于内核崩溃问题的跟踪方法,我在这里借 xxx 提供的这个死机现场,再给大家描述一下这类问题的分析方法和 debug 过程,也希望能让大家真正掌握这类问题的调试方法。让大家明白,内核崩溃问题的调试方法其实也就是这样一些固定的套路。问题的分析过程如下:

阅读全文 »
0%