库代码覆盖率
静态/共享库和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公司在芬兰以及/或其他国家的商标。所有其他商标均为其各自所有者的财产。