上述实例是程序运行顺利并产生正确结果,但是软件仍存在内存引用错误。这些错误往往是难以发现的,直到被某次运行所触发,导致程序发生故障或者崩溃。
4.2 内存泄露如果一个动态分配的内存不能被释放,我们就称为“内存泄漏”或“内存丢失”。例如,某指针指向一个动态分配的内存块,程序执行中由于某种原因改变了该指针而没有保存,这时程序中就不再含有指向该内存块的任何指针,也无法再释放它,从而造成内存垃圾,内存泄漏是最严重的内存错误之一。
Insure++能够检测和区分多种类型的内存泄漏:
·LEAK_ASSIGN:由于指针再分配,引起指针原先指向的内存块丢失;
·LEAK_FREE:释放一个含有指向其它内存块的指针的内存块。如果没有其它指针指向第二个内存块,它将永远地丢失;
·LEAK_RETURN:一个函数返回一个指向已分配内存块的指针,但该返回值被调用代码忽略;
·LEAK_SCOPE:一个函数含有指向某内存块的局部变量,但函数返回时没有将指针保存在全局变量或返回到调用代码中。
如用下列参数运行实例2程序:
hello this is a test
实例2:
1: /*
2: * File: hello.c
3: */
4: #include
5:
6: main(argc, argv)
7: int argc;
8: char *argv[];
9: {
10: char *str, *str_so_far;
11: int i, length;
12:
13: length = 1; /* Include last NULL */
14:
15: for(i=0; i
16: length += strlen(argv[i])+1;
17: str = malloc(length);
18: /*
19: * Copy the str built so far.
20: */
21: if(str_so_far != (char *)0)
22: strcpy(str, str_so_far);
23: else *str = '';
24:
25: strcat(str, argv[i]);
26: if(i < argc-1) strcat(str, ' ');
27: str_so_far = str;
28: }
29: printf('You entered: %s ', str);
30: }
在执行到27行之前检查程序的状态:
变量str_so_far指向字符串“hello”,它被分配作为前一个循环的结果。 变量str指向扩展的字符串“hello this”,在当前循环中分配。 即两个指针指向不同的内存块:
str→ |
hello this |
|
string_so_far→ |
hello |
|
执行第27行以后,
string_so_far = string;
两个变量都指向同一块:
string_so_far,str→ |
hello this |
|
hello |
上图形象地表示了指针的变化过程,开始两个变量分别指向不同的动态分配内存块,当执行第27行后,两个变量都指向较长的内存块,而没有任何指针指向较短的内存块。导致内存泄漏,即这块原先由str_so_far指示的永久分配的内存块已无法再重新使用。
**LEAK_ASSIGN** [hello.c:27]
>> str_so_far = str; ←检测到问题的源代码行
Memory leaked due to reassignment:str ←问题描述和问题表达式
Lost block: 0x0001fbb0 thru0x0001fbb6 (7bytes) ←泄漏内存块
block allocated at: malloc() (interface)
main() hello.c, 17
Stacktrace where the error occurred: ←引起问题的准确代码行位置
main() hello.c, 27
4.3.内存分配用库函数通常比较复杂,因为传递不正确的参数会导致不同的错误。调试这样的问题通常比修改自己的代码更困难,一般对库函数的运行机能了解很少。比如有一类错误的产生是由于用new(malloc)分配一个内存块而用free(delete)释放,虽然编译器允许这样做,但它可能导致兼容性问题。Insure++区分两种可能引起这类问题的情况。
·badfree:用new或new[]分配内存,用free释放。
·baddelete:用malloc分配内存,用delete或delete[]释放。
下列代码显示了一个这样的典型错误。
1: /*
2: * File: alloc2.cpp
3: */
4: #include <stdlib.h>
5:
6: int main() {
7: char *a;
8:
9: a = (char *) malloc(1);
10: delete a;
11: return 0;
12: }
当该程序经Insure++编译和运行,报告一个“内存分配冲突”错误。
[alloc2.cpp:10]**ALLOC_CONFLICT**
>> delete a;
Memory allocation conflict: a
delete operator used to deallocate memory not
allocated by new
block allocated at:
malloc()(interface)
main()alloc2.cpp,9
Stack trace where theerror occurred:
main()alloc2.cpp,10
5总结软件的内存错误通常是比较隐蔽的,由我们不知觉的编程习惯或无意的错误引入,并且在一开始大多不会引起程序的异常运行。免费论文参考网。但如果因此而未被排除,随着时间的积累、运行强度的增加等等,最终会暴露出来,导致程序失效、软件崩溃甚至更严重的无法估量的后果。使用测试工具,尽早发现、尽可能多的在前期解决隐患,对于提高软件测试的覆盖度和有效性、节约开发成本、提升软件质量都有着重要的意义。
参考文献:
[1].黎连叶等.软件测试与测试技术[M].北京:清华大学出版社,2009
[2].柳纯录等.软件评测师教程[M].北京:清华大学出版社,2005
2/2 首页 上一页 1 2 |