如何使用EASTL跟踪内存使用情况?

时间:2017-03-02 20:45:00

标签: c++ stl eastl

电子艺术EASTL图书馆的east::allocator要求用户实施特殊的new运算符(如此sample所示)。此new运算符具有const char* name,应该用于记录有关已执行EASTL容器的内存分配的特定于应用程序的信息。 EASTL Best Practices指南还提到应该“命名容器以跟踪内存使用情况。

但是,const char* name似乎没有传递任何相应的eastl::allocator::deallocate,因此似乎没有内置的记录内存解除分配的方法。

如何使用此EASTL调试功能?我想我一定错过了什么。 EA软件工程师在2015年还提供了一个相关的presentation,在那里他展示了EA为内存调试开发的一些内部工具,它似乎建议他们跟踪分配和解除分配(例如,确保内存)当“游戏等级2”开始时,“游戏等级1”被释放。

1 个答案:

答案 0 :(得分:0)

EASTL的分配器是有状态的并绑定到容器的实例;意味着它们是在实例级别定义的:

  

EASTL所做的是使用更熟悉的内存分配模式   因此,只有一个分配器类接口,它被使用   所有容器。此外,EASTL容器可让您访问他们的   分配器和查询它们,命名它们,改变它们等等。

     

EASTL选择不在容器之间复制分配器   在容器交换和分配操作期间。这意味着如果   容器A将其内容与容器B(两个容器)交换   保留原来的分配器。同样,将容器A分配给   容器B使容器B保留其原始分配器。   等效的容器应通过operator ==报告; EASTL   如果分配器是相同的,那么它将进行智能交换,并进行强力交换   否则。

来自https://github.com/questor/eastl/blob/master/doc/EASTL%20Design.html

所以我会在allocator类中添加一个成员并跟踪其中的内存计数,如下所示:

#ifndef EASTL_CUSTOM_ALLOCATOR_H_
#define EASTL_CUSTOM_ALLOCATOR_H_

#include "new_implementation.hpp"
#include <EASTL/list.h>
#include <iostream>

#define DEBUG_MACRO

class EASTL_CustomAllocator {
public:
    EASTL_CustomAllocator(const char* pName = EASTL_NAME_VAL(EASTL_ALLOCATOR_DEFAULT_NAME))
        : m_pName(pName), m_totalAmountOfBytesAllocated(0) {
#ifdef DEBUG_MACRO
        std::cout << m_pName << ": default construct allocator" << std::endl;
#endif
    }
    EASTL_CustomAllocator(const EASTL_CustomAllocator& x)
        : m_pName(x.m_pName),
          m_totalAmountOfBytesAllocated(x.m_totalAmountOfBytesAllocated) {
#ifdef DEBUG_MACRO
        std::cout << m_pName << ": copy construct allocator" << std::endl;
#endif
    }
    EASTL_CustomAllocator(const EASTL_CustomAllocator& x, const char* pName)
        : m_pName(pName),
          m_totalAmountOfBytesAllocated(x.m_totalAmountOfBytesAllocated) {
#ifdef DEBUG_MACRO
        std::cout << m_pName << ": copy construct allocator" << std::endl;
#endif
    }

    EASTL_CustomAllocator& operator=(const EASTL_CustomAllocator& x) {
#ifdef DEBUG_MACRO
        std::cout << m_pName << ": copy assignment" << std::endl;
#endif
        m_pName = x.m_pName;
        m_totalAmountOfBytesAllocated = x.m_totalAmountOfBytesAllocated;
        return *this;
    }

    void* allocate(size_t num_of_bytes, int flags = 0) {
        m_totalAmountOfBytesAllocated += num_of_bytes;
        void* p = ::new((char*)0, flags, 0, (char*)0,        0) char[num_of_bytes];
#ifdef DEBUG_MACRO
        std::cout << m_pName << ": allocate " << num_of_bytes << " bytes" << " at: " << (void*) p << std::endl;
#endif
        return p;
    }
    void* allocate(size_t num_of_bytes, size_t alignment, size_t offset, int flags = 0) {
        m_totalAmountOfBytesAllocated += num_of_bytes;
        void* p = ::new(alignment, offset, (char*)0, flags, 0, (char*)0,        0) char[num_of_bytes];
#ifdef DEBUG_MACRO
        std::cout << m_pName << ": allocate " << num_of_bytes << " bytes" << " at: " << (void*) p << std::endl;
#endif
        return p;
    }
    void  deallocate(void* p, size_t num_of_bytes) {
        m_totalAmountOfBytesAllocated -= num_of_bytes;
#ifdef DEBUG_MACRO
        std::cout << m_pName << ": deallocate " << num_of_bytes << " bytes" << " at: " << (void*) p << std::endl;
#endif
        delete[](char*)p;
    }

    const char* get_name() const {
        return m_pName;
    }
    void        set_name(const char* pName) {
        m_pName = pName;
    }
    size_t get_totalAmountOfBytesAllocated() const {
        return m_totalAmountOfBytesAllocated;
    }

protected:
    const char* m_pName;    // Debug name, used to track memory.
    size_t m_totalAmountOfBytesAllocated;   // keeps track of the memory currently allocated
};


bool operator==(const EASTL_CustomAllocator& a, const EASTL_CustomAllocator& b) {
    if (&a == &b) {
        return true;    // allocator a and b are equal if they are the same
    }
    else {
        return false;   // otherwhise, return false, because the state m_totalAmountOfBytesAllocated needs to be increased/decreased on splice and swap
    }
}
bool operator!=(const EASTL_CustomAllocator& a, const EASTL_CustomAllocator& b) {
    return false;
}


#endif /* EASTL_CUSTOM_ALLOCATOR_H_ */

将自定义分配器类型作为模板参数传递给EASTl容器,如下所示(也可以在构造时设置具有用户定义名称的实例,甚至稍后通过set_allocator()设置):

eastl::list<int, EASTL_CustomAllocator> 
list(EASTL_CustomAllocator("EASTL Some Name"));

但我不确定如何使用调试功能。