Valgrind 一款 Linux 环境下的内存调试和性能分析工具
Valgrind是一种用于检测和调试内存错误的开源工具集。它提供了一套强大的工具,可以帮助开发人员发现和修复内存泄漏、使用未初始化的内存、访问已释放的内存等常见的内存错误。
Valgrind的主要特点和功能包括:
1. 内存错误检测(Memcheck):Valgrind能够检测到内存泄漏、使用未初始化的内存、访问已释放的内存等内存错误。它会在运行程序时对内存进行跟踪,并在发现错误时给出警告和详细的错误信息。
2. 性能分析(Callgrind):Valgrind可以对程序进行性能分析,帮助开发人员找到程序中的性能瓶颈和优化机会。它可以提供函数级别的调用图、内存分配和释放的统计信息等。
3. 线程调试(Helgrind):Valgrind支持多线程程序的调试,可以检测到线程间的竞争条件和死锁等问题。它能够跟踪线程的创建、销毁和同步操作,并提供相关的调试信息。
4. 缓存分析(Cachegrind):Valgrind可以了解程序中的缓存访问模式,找到可能存在的缓存效率问题,并进行相应的优化。
使用Valgrind可以帮助开发人员提高代码质量和性能,减少内存错误和性能问题的出现。它适用于C、C++等语言的应用程序,并且在Linux和其他类Unix系统上广泛使用。

Valgrind 工具集
// check_memory.cpp
// 编译程序
// g++ check_memory.cpp -o check_memory -g
//运行程序
// valgrind --leak-check=full --track-origins=yes -s ./check_memory
// 程序输出
// ==25448== Memcheck, a memory error detector
// ==25448== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
// ==25448== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
// ==25448== Command: ./check_memory
// .....
// ==25448== LEAK SUMMARY:
// ==25448== definitely lost: 8 bytes in 2 blocks
// ==25448== indirectly lost: 0 bytes in 0 blocks
// ==25448== possibly lost: 0 bytes in 0 blocks
// ==25448== still reachable: 0 bytes in 0 blocks
// ==25448== suppressed: 0 bytes in 0 blocks
// ==25448==
// ==25448== ERROR SUMMARY: 8 errors from 8 contexts (suppressed: 0 from 0)
#include <iostream>
int main()
{
int *ptr = new int(5);
int a;
// 内存越界读
std::cout << ptr[6] << std::endl;
// 内存越界写
ptr[6] = 1;
// 使用已经释放的内存
std::cout << *ptr << std::endl;
// 使用未初始化的变量
std::cout << a << std::endl;
// 内存泄漏
ptr = new int(5);
return 0;
}
// perf_profile.cpp
// 编译程序
// g++ perf_profile.cpp -o perf_profile -g
// 运行程序
// valgrind --tool=callgrind ./perf_profile
// valgrind callgrind_annotate callgrind.out.*
// 程序输出
// ......
// --------------------------------------------------------------------------------
// Ir
// --------------------------------------------------------------------------------
// 175,705,384 (100.0%) PROGRAM TOTALS
// --------------------------------------------------------------------------------
// Ir file:function
// --------------------------------------------------------------------------------
// ....
#include <iostream>
#include <vector>
int main()
{
std::vector<int> numbers;
for (int i = 0; i < 1000000; i++)
{
numbers.push_back(i);
}
int sum = 0;
for (int num : numbers)
{
sum += num;
}
std::cout << "Sum: " << sum << std::endl;
return 0;
}
// thread_debug.cpp
// 编译程序
// g++ thread_debug.cpp -o thread_debug -g
// 运行程序
// valgrind -tool=helgrind --history-level=approx -s ./thread_debug
// 程序输出
// ==35418== ----------------------------------------------------------------
// ==35418==
// ==35418== Possible data race during write of size 4 at 0x10C158 by thread #3
// ==35418== Locks held: none
// ==35418== at 0x1092DA: incrementCounter() (thread_debug.cpp:9)
// ==35418== by 0x109C06: void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) (invoke.h:61)
// ==35418== by 0x109BB2: std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) (invoke.h:96)
// ==35418== by 0x109B53: void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (std_thread.h:259)
// ==35418== by 0x109B23: std::thread::_Invoker<std::tuple<void (*)()> >::operator()() (std_thread.h:266)
// ==35418== by 0x109B03: std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() (std_thread.h:211)
// ==35418== by 0x4947252: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30)
// ==35418== by 0x485396A: ??? (in /usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so)
// ==35418== by 0x4B4BB42: start_thread (pthread_create.c:442)
// ==35418== by 0x4BDCBB3: clone (clone.S:100)
#include <iostream>
#include <thread>
#include <mutex>
static int counter = 0;
// 线程不安全函数
void incrementCounter()
{
counter++;
}
int main()
{
std::thread t1(incrementCounter);
std::thread t2(incrementCounter);
t1.join();
t2.join();
std::cout << "Counter: " << counter << std::endl;
return 0;
}
// check_memory.cpp
// 编译程序
// g++ check_memory.cpp -o check_memory -g
// 运行程序
// valgrind --leak-check=full --track-origins=yes -s ./check_memory
// cg_annotate cachegrind.out.*
// 程序输出
// --------------------------------------------------------------------------------
// I1 cache: 32768 B, 64 B, 8-way associative
// D1 cache: 49152 B, 64 B, 12-way associative
// LL cache: 12582912 B, 64 B, 12-way associative
// Command: ./cache_optimize
// Data file: cachegrind.out.35767
// Events recorded: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw
// Events shown: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw
// Event sort order: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw
// Thresholds: 0.1 100 100 100 100 100 100 100 100
// Include dirs:
// User annotated:
// Auto-annotation: on
// ......
#include <iostream>
int main()
{
int *ptr = new int(5);
int a;
// 内存越界读
std::cout << ptr[6] << std::endl;
// 内存越界写
ptr[6] = 1;
// 使用已经释放的内存
std::cout << *ptr << std::endl;
// 使用未初始化的变量
std::cout << a << std::endl;
// 内存泄漏
ptr = new int(5);
return 0;
}
相关推荐
-
第18问:MySQL CPU 高了,怎么办?2025-02-24 10:27:18
-
mysql索引类型 normal, unique, full text
mysql索引类型 normal, unique, full text2025-02-24 10:05:05 -
uwsgi+django+nginx 搭建部分总结2025-02-24 10:03:33
-
使用Docker配置Nginx环境部署Nextcloud2025-02-24 10:02:03
-
Nginx安装和怎么使用2025-02-24 10:00:45