2024-03-23 11:57:23 +08:00
|
|
|
#include "MemoryAllocationStackTracer.h"
|
2024-03-25 00:09:33 +08:00
|
|
|
#include <fstream>
|
2024-03-23 11:57:23 +08:00
|
|
|
#include <iostream>
|
2024-03-25 00:09:33 +08:00
|
|
|
#include <sstream>
|
2024-03-23 11:57:23 +08:00
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
void *__wrap_malloc(size_t size) {
|
|
|
|
void *address = __real_malloc(size);
|
2024-03-25 00:09:33 +08:00
|
|
|
auto self = MemoryAllocationStackTracer::instance();
|
|
|
|
if (address != nullptr && self->enabled()) {
|
|
|
|
self->push(reinterpret_cast<uint64_t>(address), MemoryAllocationStackTracer::Frame());
|
|
|
|
}
|
|
|
|
// printf("%p = malloc(%zu)\n", address, size);
|
2024-03-23 11:57:23 +08:00
|
|
|
return address;
|
|
|
|
}
|
|
|
|
|
|
|
|
void __wrap_free(void *__ptr) {
|
2024-03-25 00:09:33 +08:00
|
|
|
if (__ptr != nullptr) {
|
|
|
|
MemoryAllocationStackTracer::instance()->pop(reinterpret_cast<uint64_t>(__ptr));
|
|
|
|
}
|
|
|
|
// printf("free(%p)\n", __ptr);
|
2024-03-23 11:57:23 +08:00
|
|
|
return __real_free(__ptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void *operator new(std::size_t size) {
|
2024-03-25 00:09:33 +08:00
|
|
|
// printf("void *operator new(std::size_t size),%zu\n", size);
|
2024-03-23 11:57:23 +08:00
|
|
|
|
2024-03-25 00:09:33 +08:00
|
|
|
return malloc(size);
|
|
|
|
}
|
2024-03-23 11:57:23 +08:00
|
|
|
|
2024-03-25 00:09:33 +08:00
|
|
|
void operator delete(void *p) noexcept {
|
|
|
|
// printf("%s", "void operator delete(void *p)\n");
|
|
|
|
return free(p);
|
2024-03-23 11:57:23 +08:00
|
|
|
}
|
|
|
|
|
2024-03-25 00:09:33 +08:00
|
|
|
void *operator new[](std::size_t count) {
|
|
|
|
// printf("%s", "void *operator new[](std::size_t count)\n");
|
|
|
|
return malloc(count);
|
|
|
|
}
|
|
|
|
|
|
|
|
void operator delete[](void *ptr) noexcept {
|
|
|
|
// printf("%s", "void operator delete[](void *ptr) noexcept\n");
|
|
|
|
return free(ptr);
|
2024-03-23 11:57:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
MemoryAllocationStackTracer *MemoryAllocationStackTracer::m_instance = nullptr;
|
|
|
|
|
2024-03-25 00:09:33 +08:00
|
|
|
void MemoryAllocationStackTracer::start() {
|
|
|
|
if (!m_enabled) {
|
|
|
|
m_enabled = true;
|
2024-03-23 11:57:23 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-25 00:09:33 +08:00
|
|
|
void MemoryAllocationStackTracer::push(uint64_t address, Frame &&stacktrace) {
|
|
|
|
Infomation info;
|
|
|
|
info.time = std::chrono::system_clock::now();
|
|
|
|
info.frame = std::move(stacktrace);
|
|
|
|
m_stacktraces.insert({address, info});
|
|
|
|
// m_stacktraces.insert({address, stacktrace});
|
2024-03-23 11:57:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryAllocationStackTracer::pop(uint64_t address) {
|
2024-03-25 00:09:33 +08:00
|
|
|
if (m_stacktraces.count(address) > 0) {
|
|
|
|
m_stacktraces.erase(address);
|
|
|
|
}
|
2024-03-23 11:57:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
MemoryAllocationStackTracer *MemoryAllocationStackTracer::instance() {
|
2024-03-25 00:09:33 +08:00
|
|
|
if (m_instance == nullptr) {
|
|
|
|
auto buffer = __real_malloc(sizeof(MemoryAllocationStackTracer));
|
|
|
|
if (buffer != nullptr) {
|
|
|
|
m_instance = new (buffer) MemoryAllocationStackTracer();
|
|
|
|
}
|
|
|
|
}
|
2024-03-23 11:57:23 +08:00
|
|
|
return m_instance;
|
|
|
|
}
|
2024-03-25 00:09:33 +08:00
|
|
|
void MemoryAllocationStackTracer::dump() {
|
|
|
|
using namespace std::chrono;
|
|
|
|
m_enabled = false;
|
|
|
|
std::cout << "size: " << m_stacktraces.size() << std::endl;
|
|
|
|
int index = 0;
|
|
|
|
auto now = std::chrono::system_clock::now();
|
|
|
|
std::ofstream ofs("test.txt");
|
|
|
|
for (auto &info : m_stacktraces) {
|
|
|
|
std::ostringstream oss;
|
|
|
|
auto duration = duration_cast<seconds>(now - info.second.time);
|
|
|
|
oss << "-----index[" << index << "] duration: " << duration.count() << "s:-----" << std::endl;
|
|
|
|
oss << info.second.frame << std::endl;
|
|
|
|
auto content = oss.str();
|
|
|
|
ofs << content;
|
|
|
|
std::cout << content;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
m_enabled = true;
|
|
|
|
}
|