3

の代わりにマクロを使用してnew、デバッグ モードで追加情報を取得します。

#if defined(_DEBUG)
#define SAGE_NEW new(__FUNCTION__, __FILE__, __LINE__)
#else
#define SAGE_NEW new
#endif

これは、カスタム メモリ プロファイリングとメモリ リーク検出に非常に役立つことがわかりました。共有ポインターの使用を開始したばかりなので、次のようなヒープ オブジェクトを作成しています。

auto myThingy = std::shared_ptr<Thingy>(SAGE_NEW Thingy(Args) );

std::make_shared使用するメモリ割り当てが少ないため、優先されることを知りました。に私のものを含める方法はありますSAGE_NEWmake_shared? リーク検出には問題ないことはわかっていますが、メモリ使用量の統計には引き続き使用したいと思います。allocate_sharedなんとなく答えが見えてきたような気がしますが、私にはわかりませんでした。ありがとう!:)

編集:について質問する人へnew-私はカスタムでそれをオーバーロードしますnew。コンパイラ オプション SAGE_MEM_INFO は、リーク検出とメモリ使用統計をオンにします。それ以外の場合は、ログをスキップしてメモリ プールの割り当てに直接移動します。new[] と delete[] のバリアントがありますが、簡潔にするために省略しています。

#ifdef SAGE_MEM_INFO
void* operator new  (size_t size){ ++appAllocs; return myAlloc(size); }
void* operator new  (size_t size, char const *function, char const *filename, int lineNum)
{
    ... Log memory usage
    void* ptr = ::operator new(size);
    return ptr;
}
void  operator delete   (void* ptr)
{
    ... Log freeing of this pointer
    --appAllocs;
    myFree(ptr);
}
void  operator delete   (void* ptr, char const *function, char const *filename, int lineNum)
{
    ... Log freeing of this pointer
    --appAllocs;
    myFree(ptr);
}
#else
void* operator new  (size_t size){ return myAlloc(size); }
void* operator new  (size_t size, char const *function, char const *filename, int lineNum)
{
    void* ptr = ::operator new(size);
    return ptr;
}
void  operator delete  (void* ptr) { myFree(ptr); }
void  operator delete  (void* ptr, char const *function, char const *filename, int lineNum) { myFree(ptr); } 
#endif
4

3 に答える 3

1

はい、もちろんできます。

それでも、毒を選択する必要があります。

  • 空ではないが、少なくともポインターを保存するアロケーター型を使用します。
  • 割り当てごとに新しい allocator-type を使用します。これは、参照カウントの新しいポリモーフィック タイプに反映されます。

http://en.cppreference.com/w/cpp/concept/Allocatorは、要件と適切な最小限のアロケーター宣言を示しています。

std::allocatorここで最初のオプションに適応:

#if defined(_DEBUG)
template <class Tp>
struct DebugLinesAllocator : std::allocator<Tp> {
  const char* func, *file;
  int line;
  Tp* allocate(std::size_t n, const void* = 0)
  {return ::operator new(n * sizeof(T), func, file, line);}
  template< class U > struct rebind { typedef DebugLinesAllocator<U> other; };
  DebugLinesAllocator(const char* func, const char* file, int line)
  : func(func), file(file), line(line) {}
  template< class U > DebugLinesAllocator( const DebugLinesAllocator<U>& other )
  : func(other->func), file(other->file), line(other->line) {}
};
#define SAGE_MAKE_SHARED(type, ...) allocate_shared<type>(DebugLinesAllocator<type>\
    {__FUNCTION__, __FILE__, __LINE__}, __VA_ARGS__)
#else
#define SAGE_MAKE_SHARED(type, ...) make_shared<type>(__VA_ARGS__)
#endif

それでも、共有ポインタにはあまり役に立ちません。とにかく、少しでも役に立ちます。

のように使う

auto p = SAGE_MAKE_SHARED(my_type, my_argument_1, ...);
于 2014-09-20T14:21:39.447 に答える
0

質問ではなく回答で投稿...

私のコンパイラは、Deduplicator の回答でいくつか気に入らなかった点があります。以下は完全に間違っているようには見えません。

template <class Tp>
struct DebugLinesAllocator : std::allocator<Tp> {
    char const * func;
    char const * file;
    int line;
    DebugLinesAllocator(char const * aFunc, char const * aFile, const int aLine) : func(aFunc), file(aFile), line(aLine) {}
    Tp* allocate(std::size_t n, const void* = 0)
    {
        return static_cast<Tp*> (::operator new(n * sizeof(Tp), func, file, line));
    }
    template< class U > struct rebind { typedef DebugLinesAllocator<U> other; };
    template< class U > DebugLinesAllocator(const DebugLinesAllocator<U>& other)
        : func(other.func), file(other.file), line(other.line) {}
};
#if defined(_DEBUG)
#define SAGE_MAKE_SHARED(type, ...) std::allocate_shared<type>(DebugLinesAllocator<type>(__FUNCTION__, __FILE__, __LINE__), __VA_ARGS__)
#else
#define SAGE_MAKE_SHARED(type, ...) std::make_shared<type>(__VA_ARGS__)
#endif

私の変更が疑わしいと思われる場合はお知らせください。

于 2014-09-21T14:06:00.487 に答える