vld编译Release遇到的各种问题

需求:

我项目中使用了一个lib,但是这个lib不支持release,所以我想在release模式下不使用,不编译这个lib

通过条件生成器,的确可以做到在release模式下不依赖这个lib

cmake_minimum_required(VERSION 3.0.0)
set(app "lear-cmake")
project(${app} VERSION 0.1.0)
include(./lib/CMakeLists.txt)


add_executable(${app} ./index.cpp)
target_link_libraries(${app} PUBLIC $<$<CONFIG:Debug>:lib>)

  • debug
    image.png
  • release
    image.png

但是这个lib在release模式下仍旧会编译,想要的预期效果是:

image.png

查到的资料显示EXCLUDE_FROM_DEFAULT_BUILD可以控制,但是不支持条件表达式

set_target_properties(${LIB_NAME} PROPERTIES
    EXCLUDE_FROM_DEFAULT_BUILD
    # ON
    # $<$<CONFIG:Release>:OFF>
    $<IF:$<CONFIG:Release>,ON,OFF>
)

vld_x86是可以生成release版本的

预处理器

在Debug模式下才添加_DEBUG预处理器

if(MSVC)
    target_compile_definitions(${vld} PRIVATE
        UNICODE
        _UNICODE
        _WIN32_WINNT=0x0502
        WIN32
        _USRDLL
    )
    target_compile_definitions(${vld} PRIVATE $<$<CONFIG:Debug>:_DEBUG>)
endif(MSVC)

11

void __thiscall CaptureContext::Set(void *,void *,void *,unsigned long)" 
__forceinline void Set(HANDLE heap, LPVOID mem, LPVOID newmem, SIZE_T size);

具体看报错

error LNK2019: unresolved external symbol 
"public: void 
    __thiscall
    CaptureContext::Set(void *,void *,void *,unsigned long)"
         (?Set@CaptureContext@@QAEXPAX00K@Z) 

referenced in function 
 
"private: static void * 
    __stdcall 
    VisualLeakDetector::_HeapAlloc(void *,unsigned long,unsigned long)" 
        (?_HeapAlloc@VisualLeakDetector@@CGPAXPAXKK@Z)

是调用约束不一致导致的这个问题,相关的代码为:

class CaptureContext {
public:
    __forceinline void Set(HANDLE heap, LPVOID mem, LPVOID newmem, SIZE_T size);
}


static LPVOID   __stdcall _HeapAlloc(HANDLE heap, DWORD flags, SIZE_T size);
LPVOID VisualLeakDetector::_HeapAlloc (HANDLE heap, DWORD flags, SIZE_T size)
{
    CaptureContext cc(HeapAlloc, context_);
    cc.Set(heap, block, NULL, size);// 在winapi里面调用了c++的函数
}

这个问题在Debug模式下可以正常通过编译,但是Release就报错

也尝试将CaptureContext的Set显示声明为__stdcall,仍旧报错

解决办法:

  1. __forceinline去掉,就是因为这个导致的

  2. 生成代码时禁止优化,因为这里使用了内联,所以只需要禁用内联函数展开即可
    image.png

    image.png

  • 使用cmake设置禁用内联优化:
target_compile_options(${vld} PUBLIC $<$<CONFIG:RELEASE>:/Ob0>) # 和vs里面的值一一对应

microsoft的vc默认的是__cdecl方式,而windows API则是__stdcall,如果用vc开发dll给其他语言用,则应该指定__stdcall方式。

__cdelc: c调用规则
__stdcall:winapi
__fastcall
__thiscall:c++

1,工程中只有头文件,缺少源文件,只有声明没有定义

2,引入第三方库,工程中只有头文件,没有加载导入库(xxxx.lib)

3, 头文件,源文件中 函数声明和定义都有,
但是某个参数类型不一致

4,调用约定不一致,C++工程引用了C风格的导入库,

__forceinline

__forceinline 是一种编译器指令,它用于告诉编译器将函数的代码插入到每个调用该函数的地方,从而实现函数内联的效果。比起普通函数调用,函数内联可以减少函数调用时的开销,从而提高代码的执行效率。

需要注意的是,使用 __forceinline 并不能保证函数一定会被内联。编译器可能会忽略该指令,或者在某些情况下无法进行内联,比如递归函数、带有循环语句或复杂控制流的函数等。

另外,使用 __forceinline 也可能会导致代码体积增加,因为每个调用该函数的地方都会插入一遍函数的代码。因此,在使用 __forceinline 时需要进行权衡,根据具体情况综合考虑代码的性能和体积。

总之,__forceinline 可以用于优化代码的执行效率,但使用时需要谨慎,并根据实际情况进行权衡和调整。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MY8mkTw8' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片