以下代码来自Libaiff库。我得到以下错误完全随机(即有时我的程序工作完美无缺,有时它会被这个错误卡住,它总是在这个函数的同一点中断)。(1949,0x7fff7b82d310) malloc: * error for object 0xd00000000b400:指针被释放没有被分配*在malloc_error_break中设置一个断点来调试
我的问题是,如果r->buffer2
已经被释放,那么控制是否有可能通过语句if (r->buffer2)
并进入块以尝试执行free(r->buffer2)
?换句话说,如果r->buffer2
被释放了,难道if (r->buffer2)
不应该阻止释放再次发生吗?
static void AIFF_ReadClose(AIFF_Ref r)
{
if (r->buffer)
free(r->buffer);
if (r->buffer2)
free(r->buffer2); // THIS IS WHERE THE BREAK OCCURS EVERYTIME
Unprepare(r);
fclose(r->fd);
free(r);
return;
}
编辑:以下是AIFF_Ref
的定义:
struct s_AIFF_Ref {
FILE* fd;
int flags;
int stat; /* status */
int segmentSize;
int bitsPerSample;
int nMarkers;
int nChannels;
double samplingRate;
uint64_t nSamples;
int markerPos;
uint64_t len;
uint64_t soundLen;
uint64_t pos;
uint64_t sampleBytes;
uint64_t commonOffSet;
uint64_t soundOffSet;
uint64_t markerOffSet;
IFFType format;
IFFType audioFormat;
void* decoder;
void* pdata;
void* buffer;
size_t buflen;
void* buffer2;
size_t buflen2;
int tics;
};
typedef struct s_AIFF_Ref* AIFF_Ref;
谁能建议为什么这种奇怪的行为可能会发生,我该如何解决它?谢谢。
从文档中
free函数释放一个内存块(memblock)先前由调用callloc、malloc或realloc分配。(假设第一次自由)
如果memblock为NULL,指针被忽略,free立即返回。(你从来没有来过这里,因为你从来没有把指针设置为NULL)
试图释放一个无效的指针(指向内存块的指针)(不是由calloc、malloc或realloc分配的)可能会影响随后的分配请求并导致错误。(假设第二次免费)
如果(r -> buffer2){免费的(r -> buffer2);r->buffer2 = NULL;//总是设置指针为NULL,//如果你怀疑你可能会再次"释放"内存,
//在其他地方。}
if (r->buffer2)
{
free(r->buffer2);
r->buffer2 = NULL ;
}
这是因为,当您释放内存时,free
向您保证内存将是free
'd,但它不会向您保证它将删除或NULL
'ify写入指针变量中的值。因此,if( r->buffer2 )
为您的情况保存TRUE
,因此,流进入if
块。
当您收到错误消息时,一种可能是它之前已被释放,另一种可能是指针的值已被更改为指向另一个内存。
为了避免这种情况,你必须注意在释放指针之前不要改变它,在释放内存之后,你应该把指针设置为NULL。
根据您喜欢的文档,您已经提供了打开和关闭函数,即
AIFF_Ref AIFF_OpenFile(const char* name, int flags) ;
和
int AIFF_CloseFile(AIFF_Ref r) ;
这个调用应该释放内存。你试过吗?
对你的问题的简短回答是否定的。调用free(r->buffer2)
并不会阻止if (r->buffer2)
求值为true,然后再次调用free
。原因是free(r->buffer2)
没有修改r->buffer2
的值。你可以这样想:如果你雇佣了一家拆迁公司去摧毁一栋建筑,你递给他们一张卡片,上面写着你想要摧毁的那栋建筑的地址,卡片上写的地址会在他们摧毁了那栋建筑后突然消失吗?不。指针也不例外。它只是一个地址,存储在一个变量中,我们称之为"指针",因为它标识了一个内存地址。它所指向的内存块与指针本身不是一回事。
至于是什么原因导致了对free()
的重复调用,您没有提供足够的信息来确定,因此只能推测。
请回复您的问题和一些可能有用的附加信息。
如果r->buffer2已经被释放,if (r->buffer2)不应该阻止吗从试图再次发生的事情中解脱出来?
没有办法知道内存是否已经释放的信息。正如有人指出的那样,用'null'检查指针做了一些完整性检查,通常我们这样做。但是这只会在你的逻辑有人在释放内存后将指针设置为'null'时起作用,否则'null'检查将不起作用,你当前的代码将执行'free',因为指针在释放内存时没有分配给'null'。
通过查看地址,我认为'buffer2'有一些垃圾值,无论何时运行程序,您都应该获得不同的地址值。这可能发生在'AIFF_Ref'对象可能没有被正确初始化并且仍然持有一些垃圾值的情况下。一种方法是设置
memset((void*)r, 0, sizeof(struct s_AIFF_Ref));
这将用默认值初始化所有。这可以避免给'buffer2'变量分配任何垃圾值的可能性。
你已经提到这些是一些库的逻辑,因此我建议你使用一些动态工具来快速理解错误,并在问题发生的地方。从你的描述来看,你的程序也可能有某种内存损坏。我想我以前的帖子可能对这个问题也有用。如果您的程序是windows特定的,您应该看到以下链接:
https://stackoverflow.com/a/22074401/2724703如果您的程序是特定于Gnu/Linux的,您应该看到以下链接:
https://stackoverflow.com/a/22085874/2724703