调用_freea 真的有必要吗?
Posted
技术标签:
【中文标题】调用_freea 真的有必要吗?【英文标题】:Call to _freea really necessary? 【发布时间】:2010-10-18 14:29:23 【问题描述】:我正在使用 DevStudio 在 Windows 上以非托管的 C/C++ 进行开发。
我想在堆栈而不是堆上分配一些内存,因为我不想手动释放该内存(我知道智能指针和所有这些事情。我有一个非常具体的内存案例我需要处理的分配),类似于使用 A2W() 和 W2A() 宏。
_alloca 会这样做,但已被弃用。建议改用 malloca。但是 _malloca 文档说每次调用 _malloca 都必须调用 ___freea。然后它破坏了我使用 _malloca 的目的,我将使用 malloc 或 new。
任何人都知道我是否可以不调用 _freea 而不泄漏以及内部影响是什么?
否则,我最终将只使用已弃用的 _alloca 函数。
【问题讨论】:
请注意,_alloca 的弃用不是基于“将在未来版本的 CRT 中删除”,而是因为“存在更安全的替代品”。与旨在提供过渡期的弃用不同,此类弃用用于提高对可能问题的认识的特定目的。我会说,如果您知道大小不会很大,只需使用 _alloca。 【参考方案1】:如果您使用_malloca()
,那么您必须调用_freea()
以防止内存泄漏,因为_malloca()
可以在堆栈或堆上进行分配。如果给定大小超过_ALLOCA_S_THRESHOLD 值,它会在堆上分配。因此,调用_freea()
更安全,如果分配发生在堆栈上,它不会做任何事情。
如果您使用的是_alloca()
,从今天起似乎已被弃用;由于分配发生在堆栈上,因此无需调用 _freea()
。
【讨论】:
【参考方案2】:我之前回答过这个问题,但我错过了一些基本的东西,这意味着它只能在调试模式下工作。我将对 _malloca 的调用移到一个可以自动释放的类的构造函数中。
在调试中这很好,因为它总是在堆上分配。但是在release的时候是在栈上分配的,从构造函数返回后,栈指针被重置,内存丢失了。
我返回并采用了不同的方法,结果结合使用宏 (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 );
对于发布明显错误的内容,我深表歉意!
【讨论】:
【参考方案3】:要考虑的另一件事是使用 RAII 类来管理分配 - 当然,这只有在您的宏(或其他)可以限制为 C++ 时才有用。
如果您出于性能原因想避免撞到堆,请查看 Matthew Wilson 的 auto_buffer<>
模板类 (http://www.stlsoft.org/doc-1.9/classstlsoft_1_1auto__buffer.html
) 使用的技术。这将在堆栈上分配,除非您的运行时大小请求超过编译器时指定的大小 - 因此您可以获得大多数分配的无堆分配速度(如果您正确调整模板大小),但如果超过那个尺寸。
由于 STLsoft 在处理可移植性问题方面有很多麻烦,您可能需要查看在 Wilson 的书中描述的 auto_buffer<>
的更简单版本,"Imperfect C++".
我发现它在嵌入式项目中非常方便。
【讨论】:
对 auto_buffer 建议+1。它基本上是在做 _malloca 所做的,而不是 Windows 上的 _alloca。有一项检查可确保您不会超出堆栈限制,并且如果需要,它将进行堆分配而不是堆栈分配。不过,这也适用于 C。【参考方案4】:在每次调用 _malloca 之后调用 _freea 总是很重要的。
_malloca 与 _alloca 类似,但为您的保护添加了一些额外的安全检查和增强功能。因此,_malloca 可以在堆而不是堆栈上进行分配。如果发生这种情况,而您没有调用 _freea,则会发生内存泄漏。
在调试模式下,_malloca 总是在堆上分配,所以也应该被释放。
搜索 _ALLOCA_S_THRESHOLD 以了解有关阈值如何工作的详细信息,以及为什么存在 _malloca 而不是 _alloca,这应该是有意义的。
编辑:
已经有 cmets 建议这个人只是在堆上分配,并使用智能指针等。
堆栈分配有很多优点,_malloca 将为您提供,所以有理由想要这样做。 _alloca 将以相同的方式工作,但更有可能导致堆栈溢出或其他问题,不幸的是它没有提供很好的异常,而是倾向于仅仅破坏你的进程。 _malloca 在这方面更安全,并且可以保护您,但代价是您仍然需要使用 _freea 释放内存,因为 _malloca 可能(但在释放模式下不太可能)选择在堆上而不是在堆栈上分配。
如果您的唯一目标是避免释放内存,我建议您使用智能指针,以便在成员超出范围时为您处理内存释放。这将在堆上分配内存,但要安全,并防止您不得不释放内存。不过,这只适用于 C++ - 如果您使用的是普通的 C,这种方法将不起作用。
如果您出于其他原因尝试在堆栈上分配(通常是性能,因为堆栈分配非常非常快),我建议您使用 _malloca 并接受这样一个事实,即您需要在您的值上调用 _freea .
【讨论】:
只是好奇,但为什么对 Mitch 和我的帖子投反对票?我想知道为什么有人不同意这个评论......尤其是如果我遗漏了什么。【参考方案5】:如果您担心必须释放临时内存,并且您对智能指针之类的事情了如指掌,那么为什么不使用类似的模式来释放超出范围的内存呢?
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
【讨论】:
【参考方案6】:要在堆栈上分配内存,只需声明一个适当类型和大小的变量。
【讨论】:
这不是我的反对意见,但我猜只是因为他专门询问 _alloca/_malloca,它们的堆栈使用模式与标准变量声明非常不同。不过,就我个人而言,我也会投票给你,因为在大多数情况下,如果可能的话,我会这样做。 您不能使用简单的变量在堆栈上动态分配内存块。例如, unsigned char dataBlock[tempStorageSize] 不会编译。它需要在编译时知道分配块的大小。 @philibertperusse :我知道这一点。发帖者最初询问如何在堆栈上分配。以上是关于调用_freea 真的有必要吗?的主要内容,如果未能解决你的问题,请参考以下文章