• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2025-10-27 10:51 Aet 隐藏边栏 |   抢沙发  9 
文章评分 1 次,平均分 5.0

编译相关

#pragma init_seg

  1. 概述
    1. 是微软C++编译器中的一个编译指令,专门用于精细控制全局静态对象(包括静态变量)的构造和析构顺序
    2. 在解决复杂的初始化依赖或DLL加载问题时非常有用
  2. 语法

  1. 优先级
    1. compiler
      最高优先级
      此组别的对象最先构造,最后析构
      通常保留给C/C++运行时库本身使用(如 cin, cout的初始化)
    2. lib
      中等优先级
      此组别的对象在 compiler组之后构造,在 user组之前析构。适用于第三方类库供应商
    3. user
      默认及最低优先级
      大多数用户代码默认属于此组。此组别的对象最后构造,最先析构
    4. section-name
      user_defined,特殊模式
      此组别的对象不会自动初始化
      它允许你显式指定一个自定义的段(节)名称,编译器只会将所需对象的构造函数指针放置在该命名的段中,而不会自动调用它们
      你的代码必须手动遍历该段并调用每个构造函数来完成初始化
  2. 示例

dll相关

关于dll延迟加载

  1. 隐式加载
    1. 一个dll的使用需要依赖头文件和Lib文件,直接以普通的接口的方式来调用dll的函数,这种方式就是隐式加载
      加载dll,链接了lib,这种情况lib是作为导入库,区别于加载静态库时lib是作为静态库
    2. dll的隐式加载默认会在 mian 之前进行dll的加载工作
  2. 显示加载
    1. dll的加载是通过 loadLibrary 实现,函数调用通过 GetProcAddress 来实现
  3. 延迟加载-显示加载
    1. 对于DLL的显示加载实现延迟加载比较容易,因为LoadLibrary的调用时机可以通过代码来控制
  4. 延迟加载-隐式加载
    1. 默认的隐式加载的dll是在mian函数发生之前触发,无法做到延迟加载
    2. windows提供了一种解决方案,在工程项目中设置延迟加载的dll即可实现延迟加载
    3. 链接器-输入-延迟加载的Dll
  5. 相关注意项
    1. 延迟加载是 针对隐式链接DLL
    2. 一个导出了字段(如全局变量)的DLL是无法延迟载入的
    3. 系统的DLL一般都是无法延迟载入的,如Kernel32.dll
  6. 需要链接下面的库

dll双形态在不同系统的表现

  1. win10,win11,运行正常
  2. win7上面,调试发现,会在BuildRuntime内部这一行奔溃
    1. 解决:
    2. 调试发现,编出来的release开着优化时存在此问题,而禁用优化(/Od)后则不存在
    3. 于是把release的优化关掉了来处理此问题

vs相关

符合模式

  1. 编译器选项
    1. /permissive
    2. 核心目标是让编译器以更严格的标准C++规则来检查你的代码
  2. 特点
    1. 严格遵循C++标准,禁用大部分微软特定扩展
    2. 严格,能识别并报告不符合标准的代码

threadSafeInit

  1. 概述

    1. C++11 标准规定局部静态变量的初始化必须是线程安全的,MSVCVS2015 起默认启用了这个特性(/Zc:threadSafeInit
    2. 编译器会自动在静态局部变量初始化时加锁,防止多线程重复初始化
  2. 开启

    1. /Zc:threadSafeInit
    2. 当代码首次执行到局部静态变量的声明时,编译器会插入额外的线程安全保证代码
    3. 这通常涉及使用互斥锁或类似原子操作进行双重检查(Double-Checked Locking),确保即使多个线程同时调用,该变量也只会被初始化一次
  3. 禁用

    1. /Zc:threadSafeInit-
    2. 表示禁用 C++11 的线程安全静态局部变量初始化
    3. 编译器会移除以保证线程安全而添加的同步机制
    4. 意味着,如果多个线程在同一时刻首次访问该局部静态变量,可能会同时执行初始化代码,导致未定义行为
    5. 常见后果包括重复构造对象、资源泄漏,或者更严重地,一个线程可能使用到另一个线程尚未完成初始化的对象,进而引发程序崩溃
  4. 常见禁用原因:

    1. 避免隐式依赖 CRT 同步原语,比如在 DLL 加载早期(DllMain 中)使用静态局部变量可能导致死锁
    2. 兼容老代码,某些项目原本就不依赖这个保证,关掉可以避免引入额外开销或兼容性问题
    3. 减小代码体积,省去编译器生成的锁相关代码
  5. 注意

    1. 关掉后,如果多个线程同时首次访问同一个局部静态变量,就可能出现竞态条件,需要自己保证线程安全
  6. 位置

    1. 配置属性-c/c++-命令行-附加选项

strictStrings

  1. 概述
    1. 一个一致性模式设置,它直接影响编译器对字符串字面量类型转换的严格程度
  2. 开启
    1. /Zc:strictStrings
    2. 严格遵循 C++标准
    3. 类型:严格,要求指针有 const限定
  3. 禁用
    1. /Zc:strictStrings-
    2. 宽松处理,允许非标准转换
    3. 类型:宽松,允许字符串字面量赋值给非 const指针
  4. 配置属性-c/c++-命令行-附加选项

SAFESEH

  1. 概述
    1. Windows 上针对 x8632位) 程序的一种安全机制,用于防止SEH 覆盖攻击(SEH Overwrite Attack
  2. SEH
    1. Windows 的结构化异常处理(SEH)在 x86 下是通过栈上的链表实现的
    2. 每个异常处理记录(EXCEPTION_REGISTRATION_RECORD)存放在栈上:
    3. 当异常发生时,系统沿着这个链表依次调用 Handler,直到某个 handler 处理了异常

  1. 攻击原理
    1. 因为这个链表存放在栈上,所以如果攻击者通过缓冲区溢出覆盖了栈数据,就可以:
    2. 覆盖 Handler 指针,让它指向攻击者的 shellcode
    3. 触发一个异常(比如访问非法地址)
    4. 系统沿链表调用被篡改的 Handler,跳转执行 shellcode

  1. 位置
    1. 项目属性 → 链接器 → 高级 → 映像具有安全异常处理程序
  2. 备注
    1. /SAFESEH 仅影响 x8632位)项目,x64 项目不存在这个问题

rc相关

vs rc里面覆盖资源的问题

  1. 资源视图添加了一张bitmappng下面显示IDB_PNG_TEST
  2. png下面拷贝了IDB_PNG_TEST,生成了IDB_PNG_TEST1
  3. 修改了IDB_PNG_TEST1对应的ID和文件名
  4. 用同样的流程添加了很多张图片后发现,本地对应的其他图片被修改成第一张的内容

声明:本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0 最后编辑于:2026-02-27
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享