9

我正在使用 DevStudio 在 C/C++ 非托管的 Windows 上进行开发。

我想在堆栈而不是堆上分配一些内存,因为我不想手动释放该内存(我知道智能指针和所有这些东西。我需要一个非常具体的内存分配案例处理),类似于使用 A2W() 和 W2A() 宏。

_alloca这样做,但它已被弃用。建议改用malloca。但是 _malloca 文档说每次调用 _malloca 都必须调用 ___freea。然后它破坏了我使用 _malloca 的目的,我将使用 malloc 或 new 代替。

任何人都知道我是否可以不调用 _freea 而不会泄漏以及内部影响是什么?

否则,我最终将只使用已弃用的 _alloca 函数。

4

6 回答 6

16

在每次调用 _malloca 之后调用 _freea 总是很重要的。

_malloca 类似于 _alloca,但为您的保护添加了一些额外的安全检查和增强功能。因此,_malloca 可以在堆而不是堆栈上进行分配。如果发生这种情况,并且您没有调用 _freea,您将遇到内存泄漏。

在调试模式下,_malloca 总是在堆上分配,所以也应该被释放。

搜索 _ALLOCA_S_THRESHOLD 以获取有关阈值如何工作的详细信息,以及为什么存在 _malloca 而不是 _alloca,这应该是有意义的。


编辑:

有评论表明该人只是在堆上分配,并使用智能指针等。

堆栈分配有一些优势,_malloca 将为您提供,所以有理由想要这样做。_alloca 将以相同的方式工作,但更有可能导致堆栈溢出或其他问题,不幸的是,它没有提供好的异常,而是倾向于仅仅拆除你的进程。_malloca 在这方面更安全,并且可以保护您,但代价是您仍然需要使用 _freea 释放内存,因为 _malloca 可能(但在释放模式下不太可能)选择在堆上而不是在堆栈上分配。

如果您的唯一目标是避免释放内存,我建议您使用智能指针,在成员超出范围时为您处理内存释放。这将在堆上分配内存,但要安全,并防止您不得不释放内存。不过,这仅适用于 C++ - 如果您使用的是普通的 C,这种方法将不起作用。

如果您出于其他原因尝试在堆栈上分配(通常是性能,因为堆栈分配非常非常快),我建议您使用 _malloca 并接受您需要在您的值上调用 _freea 的事实。

于 2009-04-09T16:06:13.267 回答
3

另一件要考虑的事情是使用 RAII 类来管理分配——当然,这只有在您的宏(或其他)可以限制为 C++ 时才有用。

如果您出于性能原因想避免撞到堆,请查看 Matthew Wilson 的auto_buffer<>模板类 ( http://www.stlsoft.org/doc-1.9/classstlsoft_1_1auto__buffer.html) 使用的技术。这将在堆栈上分配,除非您的运行时大小请求超过编译器时指定的大小 - 因此您可以获得大多数分配的无堆分配速度(如果您正确调整模板大小),但如果超过那个尺寸。

由于 STLsoft 在处理可移植性问题上有很多麻烦,您可能希望查看auto_buffer<>Wilson 的书“不完美的 C++”中描述的更简单的版本。

我发现它在嵌入式项目中非常方便。

于 2009-04-09T17:10:24.187 回答
1

要在堆栈上分配内存,只需声明一个适当类型和大小的变量。

于 2009-04-09T16:01:19.317 回答
1

我之前回答过这个问题,但我错过了一些基本的东西,这意味着它只能在调试模式下工作。我将对 _malloca 的调用移到将自动释放的类的构造函数中。

在调试中这很好,因为它总是在堆上分配。但是,在释放时,它在堆栈上分配,并且在从构造函数返回时,堆栈指针已被重置,并且内存丢失。

我回去采用了不同的方法,结果结合使用宏 (eurgh) 来分配内存并实例化一个将自动在该内存上调用 _freea 的对象。由于它是一个宏,它被分配在同一个堆栈帧中,因此实际上可以在释放模式下工作。它和我的课一样方便,但使用起来略逊一筹。

我做了以下事情:

class EXPORT_LIB_CLASS CAutoMallocAFree
{
public:
    CAutoMallocAFree( void *pMem ) : m_pMem( pMem ) {}
    ~CAutoMallocAFree() { _freea( m_pMem ); }

private:
    void    *m_pMem;

    CAutoMallocAFree();
    CAutoMallocAFree( const CAutoMallocAFree &rhs );
    CAutoMallocAFree &operator=( const CAutoMallocAFree &rhs );
};

#define AUTO_MALLOCA( Var, Type, Length ) \
    Type* Var = (Type *)( _malloca( ( Length ) * sizeof ( Type ) ) ); \
    CAutoMallocAFree __MALLOCA_##Var( (void *) Var );

这样我可以使用以下宏调用进行分配,并且在实例化的类超出范围时释放它:

            AUTO_MALLOCA( pBuffer, BYTE, Len );
            Ar.LoadRaw( pBuffer, Len );

对于发布明显错误的内容,我深表歉意!

于 2013-08-22T10:54:37.127 回答
0

如果您担心必须释放临时内存,并且您对智能指针之类的东西了如指掌,那么为什么不使用类似的模式来释放超出范围的内存呢?

template <class T>
class TempMem
{
  TempMem(size_t size)
  {
    mAddress = new T[size];
  }

  ~TempMem
  {
    delete [] mAddress;
  }

  T* mAddress;
}

void foo( void )
{
  TempMem<int> buffer(1024);

  // alternatively you could override the T* operator..
  some_memory_stuff(buffer.mAddress);

  // temp-mem auto-freed
}
于 2009-04-09T16:58:53.030 回答
0

如果您正在使用,_malloca()那么您必须调用_freea()以防止内存泄漏,因为_malloca()可以在堆栈或堆上进行分配。如果给定大小超过_ALLOCA_S_THRESHOLD 值,它会在堆上分配。因此,_freea()如果分配发生在堆栈上,调用 which 不会做任何事情会更安全。

如果您使用_alloca()的似乎从今天开始已被弃用;_freea()由于分配发生在堆栈上,因此无需调用。

于 2017-05-07T21:31:06.197 回答