库代码覆盖率
静态/共享库和DLL的代码覆盖率
在链接操作过程中,如果使用CoverageScanner
编译共享库,则CoverageScanner将包括共享库的所有工具指令。CoverageBrowser在一个视图中显示完整应用程序(可执行文件及其库)的代码覆盖率。
注意:要分析库的代码覆盖率,必须编译主应用程序,并通过在命令行中添加--cs-exclude-file-abs-regex=.*
等来排除其源代码,例如。
插件/手动加载的共享库的代码覆盖率
动态加载的库也可以进行工具化,但需要处理主应用程序或插件代码中执行报告的生成。
从主应用程序直接生成代码覆盖率信息
可以使用CoverageScanner API的注册/注销机制来处理主应用程序中的插件。在加载库后调用__coveragescanner_register_library()
,在卸载之前调用__coveragescanner_unregister_library()
。
示例
* #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> int main(int argc, char **argv) { void *handle; double (*cosine)(double); char *error; handle = dlopen("libm.so", RTLD_LAZY); #ifdef __COVERAGESCANNER__ __coveragescanner_register_library("libm.so"); #endif if (!handle) { fprintf(stderr, "%s\n", dlerror()); exit(EXIT_FAILURE); } dlerror(); /* Clear any existing error */ /* Writing: cosine = (double (*)(double)) dlsym(handle, "cos"); would seem more natural, but the C99 standard leaves casting from "void *" to a function pointer undefined. The assignment used below is the POSIX.1-2003 (Technical Corrigendum 1) workaround; see the Rationale for the POSIX specification of dlsym(). */ *(void **) (&cosine) = dlsym(handle, "cos"); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); exit(EXIT_FAILURE); } printf("%f\n", (*cosine)(2.0)); #ifdef __COVERAGESCANNER__ __coveragescanner_unregister_library("libm.so"); #endif dlclose(handle); exit(EXIT_SUCCESS); }
注意:可以在未进行工具化的库上调用__coveragescanner_register_library()
或__coveragescanner_unregister_library()
。
从插件直接生成代码覆盖率信息
CoverageScanner无法在链接阶段处理插件的工具化(即手动加载的共享库)。在这种情况下,库必须初始化并存储执行。因此,共享库需要在初始化时通过调用__coveragescanner_filename()
设置执行文件名称,并在卸载时通过调用__coveragescanner_save()
保存工具化。
使用Microsoft Visual Studio生成的插件代码覆盖率
当使用Microsoft® Visual Studio®生成的DLL初始化和终止时,会调用DllMain()
函数。当reason
字段等于DLL_PROCESS_ATTACH
时,应调用函数__coveragescanner_filename()
。当reason
等于DLL_PROCESS_DETACH
时,应在退出时调用函数__coveragescanner_save()
以保存测量值。
示例
* extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) { switch( dwReason ) { case DLL_PROCESS_ATTACH: #ifdef __COVERAGESCANNER__ /* Initialization of the CoverageScanner library. */ /* Replace "mylib" with your filename without extension */ __coveragescanner_filename("mylib"); #endif ... break; case DLL_PROCESS_DETACH: ... #ifdef __COVERAGESCANNER__ /* Saves the execution report */ __coveragescanner_save(); #endif break; } return TRUE; }
使用GNU gcc生成的插件代码覆盖率
GNU编译器提供了两个属性,允许您在库加载或卸载时执行函数。
__attribute__ ((constructor)) my_init(void);
:此属性指定当库加载时调用的函数。在库的自定义初始化函数中调用函数__coveragescanner_filename()
。__attribute__ ((destructor)) my_fini(void);
:此属性指定当库卸载时调用的函数。在库终止时调用函数__coveragescanner_save()
。
示例
* static void plugin_load(void) __attribute__ ((constructor)) ; static void plugin_unload(void) __attribute__ ((destructor)) ; static void plugin_load(void) { #ifdef __COVERAGESCANNER__ /* Initialization of the CoverageScanner library. */ /* Replace "mylib" with your filename without extension */ __coveragescanner_filename("mylib"); #endif ... } static void plugin_unload(void) { ... #ifdef __COVERAGESCANNER__ /* Saves the execution report */ __coveragescanner_save(); #endif }
Coco v7.2.0©2024 Qt公司有限公司。
Qt及其相关标志是Qt公司在芬兰以及/或其他国家的商标。所有其他商标均为其各自所有者的财产。