new和malloc(C ++)无法分配内存。如何修复/重新分配?

时间:2011-04-09 05:52:52

标签: c++

当程序仍然需要内存时,我正在处理运行时new的失败。我不希望程序停止。那么无论如何重新分配?提前谢谢!

3 个答案:

答案 0 :(得分:2)

您可以尝试在不需要时临时将对象存储到磁盘,并在需要访问它们时重新加载它们。例如,Photoshop曾经拥有自己的交换文件IIRC。但是,滚动自己的基于文件的对象存储并不容易 - 不确定是否已经有一些合适的实现。

另一方面,在您提出问题的方式中,您似乎意外地耗尽了内存 - 因此您可能已经在应用程序设计中遇到某种问题并尝试修复sympton而不是原因不一定最好的行动方案。

答案 1 :(得分:2)

请提供更多详情。

从您给出的描述中,我假设您的程序抛出了内存分配错误。 按照这种模式,至少在内存不足的情况下优雅退出。

    程序启动前
  1. 保留一些内存。 char reserveMemory = new char [1024 * 1024] // 1Mb

  2. 编写一个函数以在内存不足的情况下释放此内存并将其设置为new_handler(在一本好的c ++书中检查set_new_handler())。

  3. 释放reserveMemory后,堆上有1 Mb的内存。利用这些内存优雅地退出或通过在堆上释放不需要的对象等来恢复更多内存取决于你的技能。

答案 2 :(得分:0)

您可以在开始时为紧急情况预留一个大的静态内存块

FixedMemory<1024> fMem(4); // memsize 1024Char 
FixedHeap<1024,16> fHeap(fMem); // 1KiB/ 16Byte = 64 Blocks

// if usual allocation fails:
ptr = (ptrdiff_t) fHeap.alloc(16);// sizeof(Foo)
Foo* foo = new (ptr) Foo ();   
// make sure that Foo does not call new/malloc/...
// or you have to handle that as well
foo->~Foo;
fHeap.free(pMem);

当然,你必须实现自己的内存管理。您可以使用以下界面编写自己的Heap类:

class Heap {
protected:
    /** Initializes reference to system memory.*/
    Heap(Memory& memory) : memory(memory)
    {
    }

public:
    /** Allocate a piece of memory.
     * @param size size of the memory to allocate
     * @return pointer to allocated memory or null on error
     */
    virtual void* alloc(size_t size)=0;

    /** Free previously allocated memory.
     * @param p pointer to the memory to free
     */
    virtual void free(void* address)=0;

private:
    /** Reference to the system memory source. */
    Memory& memory;
};

最简单的实现是一个固定的Heap,它只返回一个固定长度的指针segmens(如果你试图得到更多,则返回空指针)。如果您已经知道需要分配的最大大小(sizeof(ClassToWorkWith)),这没关系。

然后你需要你固定的记忆:

template<size_t MEMSIZE>
class FixedMemory {
private:
    char MemArray[MEMSIZE];
    const size_t alignment;    
public:
    FixedMemory(size_t alignment) :  alignment(alignment)
    {
    }

    void * GetMemory()
    {
        return  (void*)((char*)MemArray);
    }
};

然后你可以像这样实现一个固定堆

template<size_t MEMSIZE, size_t BLOCKSIZE>
class FixedHeap : public Heap {
private:
    void *FreeHead;
    size_t realBlockSize;

public:
    FixedHeap(Memory& memory) : Heap(memory), FreeHead(0)
    {
            realBlockSize = BLOCKSIZE;
            if(memory.alignment < sizeof(void*))return;
            if(realBlockSize < sizeof(void*))realBlockSize = sizeof(void*);
            realBlockSize += (BLOCKSIZE%memory.alignment) ? (memory.alignment - BLOCKSIZE%memory.alignment) : 0;
            if( MEMSIZE >= realBlockSize ) {
                    char *pMemory = (char *)memory.GetMemory();
                    size_t malAlignment = (memory.alignment - (size_t)pMemory%memory.alignment)%memory.alignment;
                    size_t actualMemSize = MEMSIZE - malAlignment;
                    pMemory += malAlignment;

                    for(size_t i=0; i<actualMemSize/realBlockSize-1; i++)
                    {
                            *((ptrdiff_t *)(&pMemory[i*realBlockSize])) = (ptrdiff_t)&pMemory[(i+1)*realBlockSize];
                    }

                    *((ptrdiff_t *)(&pMemory[(actualMemSize/realBlockSize-1)*realBlockSize])) = 0;
                    FreeHead = (void *)pMemory;
            }
    }

    void* alloc(size_t size)
    {
            if( size > BLOCKSIZE || !FreeHead ) return 0;
            void *Result = FreeHead;
            FreeHead = (void *)*((ptrdiff_t *)FreeHead);
            return Result;
    }

    void free(void* address)
    {
            if( address && (! address % realBlockSize)) {
                    *((ptrdiff_t *)address) = (ptrdiff_t)FreeHead;
                    FreeHead = address;
            }
    }
};

有几个更好的选择,比如FirstFitHeap,但我只是想给你一个提示。