请解释一下崩溃的原因。我有第三方代码意外崩溃EXC_BAD_ACCESS
static int overwrite_selector(struct srm_target *srm, MARFileRemoverProgressBlock progressBlock)
{
srm->buffer = (unsigned char *)alloca(srm->buffer_size);
if(overwrite_byte(srm, 1, 0xF6, progressBlock) < 0) return -1;
return 0;
}
static int overwrite_byte(struct srm_target *srm, const int pass, const int byte, MARFileRemoverProgressBlock progressBlock)
{
memset(srm->buffer, byte, srm->buffer_size);
return overwrite(srm, pass, progressBlock);
}
Crash发生在memset(srm->buffer, byte, srm->buffer_size)所以似乎有问题分配内存为srm->缓冲区。但是如果我将alloca替换为malloc,那么一切都没问题(没有崩溃)。
我在osx 10.9上开发了ARC
我注意到苹果特有的:如果我在全局队列中运行代码会发生崩溃,但如果在主队列中运行代码则一切正常。
听起来像堆栈溢出,alloca将从堆栈中分配,因此如果您试图分配太多将导致堆栈溢出,而malloc将从更大的堆中分配。没有办法知道你什么时候用alloca溢出堆栈。
另外,请注意,由于alloca
在堆栈上分配,从函数返回的内存将不起作用,因为一旦退出函数,该内存将不再可用。因此,如果您需要使用函数外的内存,则需要使用malloc
。
这里你在函数中分配内存,
static int overwrite_selector(struct srm_target *srm, MARFileRemoverProgressBlock progressBlock)
{
srm->buffer = (unsigned char *)alloca(srm->buffer_size);
if(overwrite_byte(srm, 1, 0xF6, progressBlock) < 0) return -1;
return 0;
}
,由于使用alloca
,分配的内存将在函数返回时被释放。当你在其他函数中使用它时,会导致程序崩溃。
这里你调用了分配内存的函数中的其他函数。所以原因似乎是stackoverflow。而从alloca
中无法得知这种情况。由于alloca
在stackoverflow上的这种未定义的行为,在这种情况下使用alloca
是不好的。
由于alloca
尝试在堆栈上分配字节,因此了解堆栈大小非常重要。您可以使用如下代码检查堆栈大小的限制
#include <sys/resource.h>
void checkStackSize( void )
{
struct rlimit limits;
if ( getrlimit( RLIMIT_STACK, &limits ) == 0 )
printf( "soft_limit=%lld hard_limit=%lldn", limits.rlim_cur, limits.rlim_max );
}
当我在osx上测试时,软限制是8MB,硬限制是64MB。在iOS设备上,这两个限制都是1MB。
注意:以下内容来自alloca
的手册页alloca()依赖于机器和编译器;不鼓励使用
alloca()有点不安全,因为它不能确保指针返回指向一个有效的和的点可用的内存块。所做的分配可能超出堆栈的边界,甚至更远进入内存中的其他对象,并且alloca()无法确定这样的错误。避免alloca()使用large无界分配。