2012-04-30 1 views
0

次のコードがあります。割り当てられたメモリ、つまりRational :: deleteMemPool()を削除すると、次のコードがクラッシュします。C++での新規オーバーラップと削除のための汎用メモリ割り当てのクラッシュ

MEMPOOL値が00000000 MEMPOOL値である

として出力を取得するには、003462E8 MEMPOOL値は、我々は有効なポインタを持っているけれどもクラッシュ削除のためにここで003462E8

//です。

ここでバグとは何ですか?

#include <string> 
#include <iostream> 


template < class T > 
class MemoryPool { 
public: 
    MemoryPool (size_t size = EXPANSION_SIZE); 
    ~MemoryPool(); 
    inline void* alloc (size_t size); // Allocate a T element from the free list. 
    inline void free (void *someElement); // Return a T element to the free list. 
private: 
    MemoryPool<T> *next; // next element on the free list. 
    enum { EXPANSION_SIZE = 32}; // If the freeList is empty, expand it by this amount. 
    void expandTheFreeList(int howMany = EXPANSION_SIZE); // Add free elements to the free list 
}; 

template < class T > MemoryPool <T> :: MemoryPool (size_t size) { 
    expandTheFreeList(size); 
} 

template < class T > MemoryPool <T> :: ~MemoryPool() { 
    MemoryPool<T> *nextPtr = next; 
    for (nextPtr = next; nextPtr != NULL; nextPtr = next) { 
     next = next->next; 
     delete [] nextPtr; 
    } 
} 

template < class T > inline void* MemoryPool <T> :: alloc (size_t) { 
    if (!next) { 
     expandTheFreeList(); 
    } 

    MemoryPool<T> *head = next; 
    next = head->next; 
    return head; 
} 

template < class T > inline void MemoryPool <T> :: free (void *doomed) { 

    MemoryPool<T> *head = static_cast <MemoryPool<T> *> (doomed); 
    head->next = next; 
    next = head; 
} 

template < class T > void MemoryPool <T> :: expandTheFreeList(int howMany) { 
    // We must allocate an object large enough to contain the next pointer. 
    size_t size = (sizeof(T) > sizeof(MemoryPool<T> *)) ? sizeof(T) : sizeof(MemoryPool<T> *); 
    void *pNewAlloc = new char[size]; 
    MemoryPool<T> *runner = static_cast <MemoryPool<T> *> (pNewAlloc); 
    next = runner; 
    for (int i = 0; i < howMany ; i++) { 
     void *pNewAlloc = new char[size]; 
     runner->next = static_cast <MemoryPool<T> *> (pNewAlloc); 
     runner = runner->next; 
    } 
    runner->next = 0; 
} 

class Rational { 
public: 
    Rational (int a = 0, int b = 1) : n(a), d(b) {} 
    void *operator new(size_t size) { return memPool->alloc(size); } 
    void operator delete(void *doomed,size_t size) { memPool->free(doomed); } 

    static void newMemPool() { 
     std::cout << "mempool value is " << Rational::memPool << std::endl; 
     memPool = new MemoryPool <Rational>; 
     std::cout << "mempool value is " << Rational::memPool << std::endl; 
    } 
    static void deleteMemPool() { 
     std::cout << "mempool value is " << Rational::memPool << std::endl; 
     delete memPool; 
    } 

private: 
    int n; // Numerator 
    int d; // Denominator 
    static MemoryPool <Rational> *memPool; 
}; 

MemoryPool <Rational> *Rational::memPool = 0; 
int main() { 

    Rational *array[1000]; 

    Rational::newMemPool(); 


    // Start timing here 
    for (int j = 0; j < 1; j++) { 
     for (int i = 0; i < 10; i++) { 
      array[i] = new Rational(i); 
     } 

     for (int i = 0; i < 10; i++) { 
      delete array[i]; 
     } 
    } 

    // Stop timing here 
    Rational::deleteMemPool(); 

} 

スタックトレース:

Stack trace:> 
ReadParsing.exe!Rational::deleteMemPool() Line 75 C++ 
ReadParsing.exe!main() Line 107 C++ 
ReadParsing.exe!__tmainCRTStartup() Line 586 + 0x19 bytes C 
ReadParsing.exe!mainCRTStartup() Line 403 C 
kernel32.dll!7c817077() 
+0

スタックトレースを取得していますか? – trojanfoe

+0

スタックトレース:> \t ReadParsing.exe合理:: deleteMemPool()ライン75 \t C++ \t ReadParsing.exeメイン()ライン107 \t C++ \t ReadParsing.exe __ tmainCRTStartup()ライン586 + 0x19バイト\t C !!! \t ReadParsing.exe!mainCRTStartup()Line 403 \t C \t kernel32.dll!7c817077() – venkysmarty

+0

あなたの質問を編集しました。読みやすい形式でスタックトレースを追加しました。 OK、どちらが75行目ですか? – trojanfoe

答えて

4

あなたはあなたのメモリプールのブロックを削除している方法に問題があります。ブロックを割り当てるときは、new char[size]expandTheFreeList(i)に使用します。

しかし、あなたはそれらのブロックを削除すると、あなたはdelete [] nextPtrを使用します。

template < class T > MemoryPool <T> :: ~MemoryPool() { 
    MemoryPool<T> *nextPtr = next; 
    for (nextPtr = next; nextPtr != NULL; nextPtr = next) { 
     next = next->next; 
     delete [] nextPtr;  // <-- problem 
    } 
} 

そしてnextPtrmemoryPool<T>*ているので、あなたは間違ったことを解放している(と、それはブートにこのdestrcutorに再帰終わります)。

にその問題の行を変更する:

delete [] reinterpret_cast<char*>(nextPtr); 

事がクラッシュしない作るようです。もちろん、他の問題があるかもしれません。

+0

ありがとうございました。 – venkysmarty

関連する問題