查看内存泄露的方法
Visual Studio CRT 库方法
- 这是最直接的内置方法,特别适合在开发调试阶段快速发现问题
|
1 2 3 4 5 6 7 8 |
#define _CRTDBG_MAP_ALLOC // 确保能显示泄漏发生的文件行号 #include <crtdbg.h> int main() { _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // ... 你的代码 return 0; } |
Visual Leak Detector (VLD)
- 在包含
main()函数的源文件中包含头文件即可:#include <vld.h> - 在
Debug模式下运行程序,泄漏报告会输出到Visual Studio的“输出”窗口
Visual Studio 内存性能分析器
- 调试-性能探查器
- 对于
Release版本中出现的泄漏,或者需要分析内存使用趋势时,这个内置的性能分析工具非常强大
进阶方案
- 重载
new/delete:- 通过全局重载
new和delete运算符,可以记录每一次内存分配和释放的详细信息(如大小、指针地址、调用堆栈等)
- 通过全局重载
其他
如何实现一个高效的比较字符串的方法(非n方)
- 位图编码比较
KMP算法Boyer-Moore算法Rabin-Karp算法
用一个类的空对象指针,去调用普通函数和虚函数
- 普通函数
- 不访问数据成员,可以
- 访问数据成员,崩溃
- 虚函数
- 崩溃
this指针
this指针确实指向当前对象在内存中的首地址
|
1 |
TestClass* const |
对象的vptr
vptr类型
|
1 |
void** |
- 在
vs里面局部变量观察vptr成员,发现类型都是void*- 虚函数表在内存中本质上是一个函数指针数组,而编译器在组织和访问这个数组时,并不关心每个函数指针具体的签名(包括返回类型和参数),它只关心这些指针在内存中的顺序和地址
vptr位置- 通常位于对象内存布局的开头。这是最高效的访问方式,但
C++标准并未强制规定,编译器实现可能有差异
- 通常位于对象内存布局的开头。这是最高效的访问方式,但
RTTI存储位置- 存储在虚函数表(
vtable)之前的某个固定偏移处(通常是一个负偏移),与vtable紧密关联- 在
MSVC编译器下,这个负偏移量通常是4字节(32位)或8字节(64位),具体对应的是vptr指针向前偏移一个指针大小的位置来获取RTTICompleteObjectLocator的地址
- 在
- 存储在虚函数表(
虚函数表
- 本质
- 虚函数表可以理解为一个函数指针数组
- 这个数组在编译时由编译器静态创建,并存储在程序的只读数据段
- 数组中的每个元素,简单来说就是一个内存地址,指向一段可执行代码的起始位置
这个地址本身并不携带任何关于函数参数和返回类型的信息,它就是一个数字
- 编译期的类型安全
- 类型安全的重任完全由编译器在编译阶段完成
- 当编译器解析你的代码时,它通过基类中虚函数的声明,完全了解每一个虚函数(如
vtable[0],vtable[1])应有的正确签名(返回类型、参数列表) - 因此,当你写下
basePtr->virtualFunction()时,编译器生成的代码会:
通过对象的vptr找到虚函数表
根据函数在基类中的声明顺序(索引号)找到对应的函数地址
生成一次函数调用,并基于它已知的、正确的函数签名来处理参数传递和返回值
RTTICompleteObjectLocator
- 概述
- 它是
Microsoft Visual C++(MSVC)编译器实现运行时类型识别(RTTI) 的核心数据结构,包含了在运行时进行类型识别(typeid)和安全的跨继承层次转换(dynamic_cast)所需的全部信息
- 它是
- 成员
signature
DWORD
一个魔数签名,用于验证结构的有效性。在32位程序中通常为0x00000000offset
DWORD
核心成员。表示当前虚函数表(vftable)指针距离完整对象起始地址的偏移量
在简单单继承中,此值通常为0;在多重继承中,若当前vftable属于非首位的基类,则此值非零cdOffset
DWORD
构造位移偏移。用于在对象构造/析构过程中调整this指针,确保在非完整构造的对象上也能正确执行dynamic_castpTypeDescriptor
TypeDescriptor*
指向描述具体类型的TypeDescriptor结构体的指针。该结构体包含了类型的名称(name())等核心信息,是typeid运算符的直接数据来源pClassDescriptor
RTTIClassHierarchyDescriptor*
指向描述类继承层次的RTTIClassHierarchyDescriptor(CHD)结构体的指针
这是实现dynamic_cast的关键,它描述了类的完整继承图谱
其他
共享内存
vector迭代器失效问题
std::move
进程间通信方式
进程间通信的效率
线程间同步方式
std::atomic
快速排序
堆排序
快速排序和分治算法
用最快的时间找到单链表的中间结点在main函数之前做事情
检测堆内存泄露的手段(内存泄露工具)
CPU占用高的原因以及处理
消费者生产者的同步问题
声明:本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ 2025_03_1803/18
- ♥ 2022_02_24_0103/01
- ♥ 2020_05_11_0105/14
- ♥ 2023_02_0902/11
- ♥ 后端知识点记述 一09/08
- ♥ 2022_03_0203/09
热评文章
- 2020_05_11_01 0
- 2022_02_26 0
- 2025_03_11 0
- 2020_04_29 0
- 2022_03_09 0
- 2025_03_18 0