>我有以下C函数:
void mySwap(void * p1, void * p2, int elementSize)
{
void * temp = (void*) malloc(elementSize);
assert(temp != NULL);
memcpy(temp, p1, elementSize);
memcpy(p1, p2, elementSize);
memcpy(p2, temp, elementSize);
free(temp);
}
我想在通用排序函数中使用。假设我用它来对 main() 拥有的动态分配数组进行排序。现在让我们假设在某个时候 mySwap() 中的 temp 实际上是 NULL,并且整个程序被中止,而没有释放 main() 中动态分配的数组。我认为 mySwap() 和排序函数都可以返回一个布尔值,指示分配是否成功,并且通过使用 if 语句我可以释放 main() 和 exit(EXIT_FAILURE) 中的数组,但这似乎不是一个非常优雅的解决方案。 在这种情况下防止内存泄漏的好方法是什么?
assert
通常在调试期间用于识别不应发生的问题/错误。
内存不足是可能发生的情况,因此不应由assert
处理,或者,如果您确实使用assert
,请注意它会中止程序。程序中止后,程序使用的所有内存都将解除分配,因此不必担心。
注意:如果您不希望到处都有笨拙的if
语句,只是为了处理几乎从未发生的错误,则可以使用setjmp/longjmp
返回到可恢复的状态。
您必须意识到 malloc 失败的原因是您的计算机内存不足。从那时起,您的程序除了尽可能优雅地终止之外,没有任何有意义的事情可以执行。
操作系统将在程序终止时释放内存,因此您无需担心。
不过,在正常情况下,手动free()
自己当然是一种很好的做法。与其说是为了"使内存再次可用" - 操作系统将确保这一点 - 而是验证您的程序在此过程中没有出现严重错误并造成堆损坏,泄漏或其他错误。如果您的程序中有此类错误,它将在free()
调用期间崩溃,这是一件好事,因为错误会浮出水面。
assert
最好不要在生产代码中使用。如果需要,可以构建自己的错误处理,这比在执行过程中暴力终止自己的程序要好。
通过使用不使用malloc
来避免此问题。
不要为每个交换分配一个内存块,而是一次执行一个字节的交换;
for (int i = 0; i < elementSize; ++i) {
char tmp = ((char*)p1)[i];
((char*)p1)[i] = ((char*)p2)[i];
((char*)p2)[i] = tmp;
}
仅在开发过程中使用assert()
来捕获程序员错误,在发布版本中它不执行任何操作。如果您需要测试其他内容,请使用适当的错误处理,无论这意味着abort()
,返回代码还是使用setjmp()
/longjmp()
模拟异常。
顺便说一句,不要投射malloc()
的结果.