测量在Python进程中调用的C库覆盖率
让我先举个例子——在Python中调用库代码。
这是库代码(编译成库 libfoolib
):
#include <stdio.h>
void bar()
{
printf("bar\n");
}
void foo()
{
printf("foo\n");
}
这是调用它的Python代码:
#!/usr/bin/python25
import sys
import libfoolib
import processing
def callFoo():
libfoolib.foo()
libfoolib.bar()
process = processing.Process(target=callFoo)
process.start()
当库使用 -ftest-coverage
和 -fprofile-arcs
编译时,编译器会生成 gcno
文件,而当执行Python代码时,gcda
文件也会被生成。问题是,这个文件只包含了在Python进程分叉之前调用的 bar
函数的覆盖率数据。如果 foo
函数也在Python处理调用之外被调用,那么一切就正常了。
这是我在生成的覆盖率数据上运行 gcov
工具时得到的结果:
-: 0:Source:/codeCoverageTests/pythonSIP/foo.c
-: 0:Graph:debug/CMakeFiles/fooLib.dir/foo.c.gcno
-: 0:Data:debug/CMakeFiles/fooLib.dir/foo.c.gcda
-: 0:Runs:4
-: 0:Programs:1
-: 1:#include <stdio.h>
-: 2:
-: 3:void bar()
function bar called 4 returned 100% blocks executed 100%
4: 4:{
4: 5: printf("bar\n");
call 0 returned 100%
4: 6:}
-: 7:
-: 8:void foo()
function foo called 0 returned 0% blocks executed 0%
#####: 9:{
#####: 10: printf("foo\n");
call 0 never executed
#####: 11:}
-: 12:
我想问的问题是:“我的 foo
的覆盖率数据在哪里?”
关于环境的一些详细信息:
- CentOS 5.4
- gcc: 4.1.2 20080704 (Red Hat 4.1.2-46)
- CMake构建(版本 2.8.0)
- Python 2.5
- Python与C之间使用SIP(版本 4.7.4)
1 个回答
1
问题在于,Python的处理库使用了os._exit
来退出程序。这种退出方式有个缺点,就是不会调用正常的清理程序。也就是说,程序在结束时没有机会去做一些必要的清理工作。实际上,覆盖率工具会在程序退出时收集数据并写入,这个过程是在正常的清理程序中进行的。由于这些原因,子进程没有机会写出它的数据,所以调用foo
的结果也就没法被记录下来。
为了解决这个问题,我在程序结束前手动调用了__gcov_flush
。因为这是一个静态库,所以需要写一个小的C语言代码来完成这个任务。