add memory leak test code.
This commit is contained in:
parent
b1396e75ec
commit
4178f405f2
1
.gitignore
vendored
1
.gitignore
vendored
@ -38,4 +38,5 @@ target_wrapper.*
|
||||
|
||||
# QtCreator CMake
|
||||
CMakeLists.txt.user*
|
||||
.idea
|
||||
build
|
||||
|
1
.vscode/c_cpp_properties.json
vendored
1
.vscode/c_cpp_properties.json
vendored
@ -7,6 +7,7 @@
|
||||
"${workspaceFolder}/3rdparty/ds_pedestrian_mot_hisi/include",
|
||||
"/opt/Libraries/boost_1_84_0/include",
|
||||
"/opt/aarch64-v01c01-linux-gnu-gcc/lib/ZLMediaKit/include",
|
||||
"/opt/aarch64-v01c01-linux-gnu-gcc/lib/LeakTracer/include",
|
||||
"build/_deps/kylin-src/Universal"
|
||||
],
|
||||
"defines": [],
|
||||
|
@ -1 +1,2 @@
|
||||
add_subdirectory(LeakTracer)
|
||||
add_subdirectory(VideoRecoder)
|
18
Tools/LeakTracer/CMakeLists.txt
Normal file
18
Tools/LeakTracer/CMakeLists.txt
Normal file
@ -0,0 +1,18 @@
|
||||
add_executable(LeakTracer main.cpp
|
||||
# LeakTracer.h LeakTracer.cpp
|
||||
MemoryAllocationStackTracer.h MemoryAllocationStackTracer.cpp
|
||||
)
|
||||
|
||||
target_include_directories(LeakTracer
|
||||
PRIVATE ${Libraries_ROOT}/LeakTracer/include
|
||||
)
|
||||
|
||||
target_link_directories(LeakTracer
|
||||
PRIVATE ${Libraries_ROOT}/LeakTracer
|
||||
)
|
||||
|
||||
target_link_libraries(LeakTracer
|
||||
PUBLIC Universal
|
||||
-Wl,--wrap=malloc
|
||||
-Wl,--wrap=free
|
||||
)
|
39
Tools/LeakTracer/LeakTracer.cpp
Normal file
39
Tools/LeakTracer/LeakTracer.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include "LeakTracer.h"
|
||||
#include "DateTime.h"
|
||||
#include <leaktracer.h>
|
||||
#include <sstream>
|
||||
|
||||
LeakTracer::LeakTracer(const std::string &path, const std::string &applicationName)
|
||||
: m_path(path), m_applicationName(applicationName) {
|
||||
}
|
||||
|
||||
LeakTracer::~LeakTracer() {
|
||||
stop();
|
||||
}
|
||||
|
||||
void LeakTracer::run() {
|
||||
using namespace std::chrono;
|
||||
using namespace std::chrono_literals;
|
||||
while (!m_exit) {
|
||||
auto start = system_clock::now();
|
||||
leaktracer_startMonitoringAllThreads();
|
||||
while (!m_exit) {
|
||||
std::this_thread::sleep_for(50ms);
|
||||
auto now = system_clock::now();
|
||||
auto elapsed = duration_cast<milliseconds>(now - start);
|
||||
if (elapsed >= m_intervals) break;
|
||||
}
|
||||
std::ostringstream oss;
|
||||
oss << m_path << "/" << m_applicationName << "_" << DateTime(start).toString("%Y%m%d%H%M%S") << "-"
|
||||
<< DateTime::currentDateTime().toString("%Y%m%d%H%M%S") << ".dump";
|
||||
leaktracer_writeLeaksToFile(oss.str().c_str());
|
||||
leaktracer_stopAllMonitoring();
|
||||
}
|
||||
}
|
||||
|
||||
void LeakTracer::stop() {
|
||||
if (!m_exit) {
|
||||
m_exit = true;
|
||||
if (m_thread.joinable()) m_thread.join();
|
||||
}
|
||||
}
|
34
Tools/LeakTracer/LeakTracer.h
Normal file
34
Tools/LeakTracer/LeakTracer.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef __AMASS_LEAKTRACER_H__
|
||||
#define __AMASS_LEAKTRACER_H__
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
class LeakTracer {
|
||||
public:
|
||||
LeakTracer(const std::string &path, const std::string &applicationName);
|
||||
~LeakTracer();
|
||||
|
||||
template <class Rep, class Period>
|
||||
void start(const std::chrono::duration<Rep, Period> &intervals) {
|
||||
if (m_exit) {
|
||||
m_exit = false;
|
||||
m_thread = std::thread(&LeakTracer::run, this);
|
||||
}
|
||||
m_intervals = std::chrono::duration_cast<std::chrono::milliseconds>(intervals);
|
||||
}
|
||||
|
||||
void stop();
|
||||
|
||||
protected:
|
||||
void run();
|
||||
|
||||
private:
|
||||
bool m_exit = true;
|
||||
std::string m_path;
|
||||
std::string m_applicationName;
|
||||
std::chrono::milliseconds m_intervals;
|
||||
std::thread m_thread;
|
||||
};
|
||||
#endif // __AMASS_LEAKTRACER_H__
|
63
Tools/LeakTracer/MemoryAllocationStackTracer.cpp
Normal file
63
Tools/LeakTracer/MemoryAllocationStackTracer.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include "MemoryAllocationStackTracer.h"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
void *__wrap_malloc(size_t size) {
|
||||
void *address = __real_malloc(size);
|
||||
// if (address != nullptr) {
|
||||
// MemoryAllocationStackTracer::instance()->push(reinterpret_cast<uint64_t>(address),
|
||||
// boost::stacktrace::stacktrace());
|
||||
// }
|
||||
// std::cout << "malloc " << size << " bytes." << std::endl;
|
||||
return address;
|
||||
}
|
||||
|
||||
void __wrap_free(void *__ptr) {
|
||||
// if (__ptr != nullptr) {
|
||||
// MemoryAllocationStackTracer::instance()->pop(reinterpret_cast<uint64_t>(__ptr));
|
||||
// }
|
||||
return __real_free(__ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void *operator new(std::size_t size) {
|
||||
printf("new %d %d\n ", size, sizeof(boost::stacktrace::stacktrace));
|
||||
void *address = __real_malloc(size);
|
||||
|
||||
// if (size != sizeof(boost::stacktrace::stacktrace) || size != 2048) {
|
||||
// MemoryAllocationStackTracer::instance()->push(reinterpret_cast<uint64_t>(address),
|
||||
// boost::stacktrace::stacktrace());
|
||||
// }
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
void operator delete(void *p) {
|
||||
free(p);
|
||||
}
|
||||
|
||||
MemoryAllocationStackTracer *MemoryAllocationStackTracer::m_instance = nullptr;
|
||||
|
||||
void MemoryAllocationStackTracer::initialize() {
|
||||
if (m_instance == nullptr) {
|
||||
auto buffer = __real_malloc(sizeof(MemoryAllocationStackTracer));
|
||||
if (buffer != nullptr) {
|
||||
m_instance = new (buffer) MemoryAllocationStackTracer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryAllocationStackTracer::push(uint64_t address, const boost::stacktrace::stacktrace &stacktrace) {
|
||||
m_stacktraces.insert({address, stacktrace});
|
||||
}
|
||||
|
||||
void MemoryAllocationStackTracer::pop(uint64_t address) {
|
||||
m_stacktraces.erase(address);
|
||||
}
|
||||
|
||||
MemoryAllocationStackTracer *MemoryAllocationStackTracer::instance() {
|
||||
|
||||
return m_instance;
|
||||
}
|
76
Tools/LeakTracer/MemoryAllocationStackTracer.h
Normal file
76
Tools/LeakTracer/MemoryAllocationStackTracer.h
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef __MEMORYALLOCATIONSTACKTRACER_H__
|
||||
#define __MEMORYALLOCATIONSTACKTRACER_H__
|
||||
|
||||
#include <boost/stacktrace/stacktrace.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
extern "C" {
|
||||
extern void *__real_malloc(size_t size);
|
||||
extern void __real_free(void *__ptr);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class DebugAllocator {
|
||||
public:
|
||||
using value_type = T;
|
||||
using pointer = T *;
|
||||
|
||||
typedef const T *const_pointer;
|
||||
typedef T &reference;
|
||||
typedef const T &const_reference;
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
|
||||
template <class U>
|
||||
struct rebind {
|
||||
typedef DebugAllocator<U> other;
|
||||
};
|
||||
DebugAllocator() {
|
||||
}
|
||||
|
||||
template <class U>
|
||||
DebugAllocator(const DebugAllocator<U> &other) noexcept {
|
||||
}
|
||||
|
||||
T *allocate(std::size_t n) {
|
||||
return reinterpret_cast<T *>(__real_malloc(n));
|
||||
}
|
||||
void deallocate(T *p, std::size_t n) {
|
||||
__real_free(p);
|
||||
}
|
||||
|
||||
template <class U, class... Args>
|
||||
void construct(U *p, Args &&...args) {
|
||||
::new ((void *)p) U(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
void destroy(U *p) {
|
||||
p->~U();
|
||||
}
|
||||
|
||||
pointer address(reference x) {
|
||||
return (pointer)&x;
|
||||
}
|
||||
|
||||
const_pointer address(const_reference x) {
|
||||
return (const_pointer)&x;
|
||||
}
|
||||
};
|
||||
|
||||
class MemoryAllocationStackTracer {
|
||||
public:
|
||||
static void initialize();
|
||||
static MemoryAllocationStackTracer *instance();
|
||||
void push(uint64_t address, const boost::stacktrace::stacktrace &stacktrace);
|
||||
void pop(uint64_t address);
|
||||
|
||||
private:
|
||||
std::unordered_map<uint64_t, boost::stacktrace::stacktrace, std::hash<uint64_t>, std::equal_to<uint64_t>,
|
||||
DebugAllocator<MemoryAllocationStackTracer>>
|
||||
m_stacktraces;
|
||||
|
||||
static MemoryAllocationStackTracer *m_instance;
|
||||
};
|
||||
|
||||
#endif // __MEMORYALLOCATIONSTACKTRACER_H__
|
37
Tools/LeakTracer/main.cpp
Normal file
37
Tools/LeakTracer/main.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "LeakTracer.h"
|
||||
#include "MemoryAllocationStackTracer.h"
|
||||
#include <boost/stacktrace.hpp>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void test() {
|
||||
std::cout << boost::stacktrace::stacktrace();
|
||||
malloc(20);
|
||||
}
|
||||
|
||||
int make_memory_leak(void) {
|
||||
printf("%s:%d, 00!\n", __FILE__, __LINE__);
|
||||
|
||||
int *ptr = (int *)malloc(sizeof(int)); // 分配内存块
|
||||
*ptr = 0; // 构造内存泄露
|
||||
printf("%s:%d, ptr= %p, *ptr= %d!\n", __FILE__, __LINE__, ptr, *ptr);
|
||||
|
||||
char *p_new = new char[8 * 1024 * 1024];
|
||||
(void)memset(p_new, 0, 8 * 1024 * 1024);
|
||||
*p_new = 0;
|
||||
printf("%s:%d, p_new= %p, *p_new= %d!\n", __FILE__, __LINE__, p_new, *p_new);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
class Test {
|
||||
int a;
|
||||
};
|
||||
|
||||
int main(int argc, char const *argv[]) {
|
||||
MemoryAllocationStackTracer::initialize();
|
||||
auto a = new Test();
|
||||
return 0;
|
||||
}
|
@ -62,6 +62,7 @@ function init() {
|
||||
echo "put /opt/aarch64-v01c01-linux-gnu-gcc/lib/gdb-10.2/bin/gdbserver /system/bin" | sftp -i resources/ssh_host_rsa_key_ok root@${TARGET_IP}
|
||||
ssh -i resources/ssh_host_rsa_key_ok root@${TARGET_IP} "mkdir -p /data/sdcard/PassengerStatistics/lib"
|
||||
echo "put /opt/aarch64-v01c01-linux-gnu-gcc/lib/ZLMediaKit/lib/libmk_api.so /data/sdcard/PassengerStatistics/lib" | sftp -i resources/ssh_host_rsa_key_ok root@${TARGET_IP}
|
||||
echo "put /opt/aarch64-v01c01-linux-gnu-gcc/lib/LeakTracer/libleaktracer.so /data/sdcard/PassengerStatistics/lib" | sftp -i resources/ssh_host_rsa_key_ok root@${TARGET_IP}
|
||||
# echo "put ${BOOST_LIBDIR}/libboost_date_time* /system/lib" | sftp -i resources/ssh_host_rsa_key_ok root@${TARGET_IP}
|
||||
echo "put ${BOOST_LIBDIR}/libboost_regex.so.1.84.0 /system/lib" | sftp -i resources/ssh_host_rsa_key_ok root@${TARGET_IP}
|
||||
echo "put ${BOOST_LIBDIR}/libboost_log_setup.so.1.84.0 /system/lib" | sftp -i resources/ssh_host_rsa_key_ok root@${TARGET_IP}
|
||||
@ -87,7 +88,7 @@ function deploy() {
|
||||
echo "deploy to target $TARGET_IP, path: ${TARGET_PATH} ..."
|
||||
echo "put ${build_path}/Main/PassengerStatistics ${TARGET_PATH}" | sftp -i resources/ssh_host_rsa_key_ok root@${TARGET_IP}
|
||||
echo "put ${build_path}/Tools/VideoRecoder/VideoRecoder ${TARGET_PATH}" | sftp -i resources/ssh_host_rsa_key_ok root@${TARGET_IP}
|
||||
|
||||
echo "put ${build_path}/Tools/LeakTracer/LeakTracer ${TARGET_PATH}" | sftp -i resources/ssh_host_rsa_key_ok root@${TARGET_IP}
|
||||
ssh -i resources/ssh_host_rsa_key_ok root@${TARGET_IP} "sync"
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user