首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

使用 DrMemory 发现内存编程错误(3)

使用 DrMemory 发现内存编程错误(3)

未初始化读读取未初始化的内存其结果是未知的,使用这样的数据是很危险的。让我们查看下面这个测试程序(并不危险的程序):
清单 3,未初始化错误例子程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1:       typedef struct T_ {
2:         char a;
3:         char b;
4:       }T;

5:       int main()
6:       {
7:         T a,b;
8:         char x;
9:         a.a = 'a';
10:        a.b = 'b';
11:        b.a = x;
12:        if(b.a ==10)
13:           memcpy(&b,&a, sizeof(T));
14:        return 0;
15:       }




运行 DrMemory 得到如下报告:
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
Dr. Memory results for pid 24399, …

Error #1: UNINITIALIZED READ: reading register al
# 0 t!main                             [/home/DrMem/uninit.c:16]
# 1 libc.so.6<nosyms>!?
# 2 t!_start
Note: elapsed time = 0:00:00.111 in thread 24399
Note: instruction: cmp    %al $0x0a

========================================================
FINAL SUMMARY:
Grouping errors that may be the same or related:
Group 1:
Group 2:  1
DUPLICATE ERROR COUNTS:
SUPPRESSIONS USED:
ERRORS FOUND:
      0 unique,     0 total unaddressable access(es)
      1 unique,     1 total uninitialized access(es)
      0 unique,     0 total invalid heap argument(s)
      0 unique,     0 total warning(s)
      0 unique,     0 total,      0 byte(s) of leak(s)
      0 unique,     0 total,      0 byte(s) of possible leak(s)
ERRORS IGNORED:
      0 still-reachable allocation(s)




可以看到 DrMemory 只报告了一个未初始化读错误,在第 12 行。很多其他工具对于 memcpy(&b,&a, sizeof(T))也会报错。
GCC 将自动对齐数据结构(未使用 pack 修饰符的情况下)。因此 struct T 在内存中的实际分布如下:
图 3. 内存拷贝细节在 memcpy 时,有 3 个未初始化 byte 也被访问了,但这类错误如果也报告的话,对正常程序 DrMemory 会产生很多错误信息。这些其实不是错误,所以被称为 False Positive。类似医学名词“假阳性”。内存调试工具的一个主要目标就是减少 False Positive,否则产生的报告有用性将极大降低。
其它很多工具,遇到上述拷贝会报告 false positive,浪费读报告的人们的时间。因此这是 Dr Memory 的一个重要优点。
Heap 操作参数错误(Invalid Heap Argument)C 语言用 malloc()、free()等函数处理内存 heap 的使用。如果使用不当,会造成未知后果,比如传入 free()的参数不正确,可能造成 crash,或者用 new 分配,却用 free 来释放内存。这类错误 DrMemory 称之为 Invalid Heap Argument 错误。
比如下面这个 C++程序:
清单 4.非法 Heap 操作参数
1
2
3
4
5
6
7
8
9
//invalidArg.cpp
4:  int main()
5:  {
6:    char * ptr = NULL;
7:    ptr = new char;
8:    free(ptr);
9:    free(ptr);
10:   return 0;
11:  }




运行 DrMemory 检测上述程序,将产生两个错误信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Error #1: INVALID HEAP ARGUMENT:
allocated with operator new, freed with free
# 0 t!main             [/home/DrMem/invalidArg.cpp:8]
# 1 libc.so.6<nosyms>!?
# 2 t!_start
Note: elapsed time = 0:00:00.165 in thread 27804
Note: memory was allocated here:
Note: # 0 libstdc++.so.6<nosyms>!?
Note: # 1 t!main      [/home/DrMem/invalidArg.cpp:7]
Note: # 2 libc.so.6<nosyms>!?

Error #2: INVALID HEAP ARGUMENT to free() 0x0804a018
# 0 t!main        [/homeDrMem/invalidArg.cpp:9]
# 1 libc.so.6<nosyms>!?
# 2 t!_start
Note: elapsed time = 0:00:00.167 in thread 27804
Note: memory was previously freed




Error#1 表示在程序的第 8 行,用 C 风格的 free 来释放一个用 new 操作符分配的内存。这是一个错误。
在第 9 行,出现了 free 两次的错误,这也是不当使用内存堆分配函数的典型例子。
通过 Dr Memory,我们可以方便地检测到程序中这类不当使用内存函数和操作符的地方。
返回列表