在C
中,我知道最好在分配后始终检查新malloced变量是否为null
。如果是这样,我可以输出错误,例如perror
并退出该计划。
但是在更复杂的程序中呢?例如。我main
调用函数f1
(返回int
),调用函数f2
(返回char*
),调用函数{{ 1}}(返回f3
),我在double
内没有malloc。
在这种情况下,我似乎只是输出错误并退出(如果可能的话甚至可能有内存泄漏),因为f3
仍会强迫我先返回f3
。然后double
会强制我返回f2
等等。在这种情况下,跟踪错误并适当退出似乎非常痛苦。什么是有效地覆盖这些功能的错误的正确方法?
答案 0 :(得分:1)
显而易见的解决方案是小心设计程序,以便执行动态分配的每个函数都有一些报告错误的方法。大多数情况下,函数的返回值用于此目的。
在精心设计的程序中,错误会在调用堆栈中一直向上反弹,以便在应用程序级别处理它们。
在动态内存分配的特定情况下,最好尽可能将分配留给调用者。
答案 1 :(得分:1)
这总是一个问题。你需要一种不熟悉的方法。
首先,每个动态指针必须是"拥有"有人。 C不会在这里帮助你,你只需要指定。通常这三种模式是
a)函数调用malloc(),然后调用free():
b)我们有两个匹配的函数,一个返回缓冲区或动态 结构,一个破坏它的结构。调用create的函数也会调用destroy。
c)我们在整个程序中随机插入一组节点。它需要像b一样进行管理,一个函数创建根,然后调用删除它来破坏整个图。
规则是所有者保留并释放。
如果返回指针,则在内存不足时返回0。如果返回整数,则返回-1。错误会被传播,直到某些高级代码知道哪些用户级操作失败并中止它。
答案 2 :(得分:1)
其他答案是正确的,正确处理此问题的方法是确保每个可以分配内存的函数都可以向其调用者报告失败,并且每个调用者都会处理这种可能性。当然,您有一个测试malloc
垫片,可以安排测试每个可能的分配失败。
但是在大型C程序中,这变得难以处理 - 对于初学者来说,需要测试的案例数量会增加指数与malloc
个callite的数量 - 所以很常见utils.c
文件中的这样一个函数:
void *
xmalloc(size_t n)
{
void *rv = malloc(n);
if (!rv) {
fprintf(stderr, "%s: memory exhausted\n", program_name);
exit(1);
}
return rv;
}
程序中的所有其他代码始终调用xmalloc
,而不是malloc
,并且可以假设它始终成功。 (你还有xcalloc
,xrealloc
,xstrdup
等。
图书馆无法摆脱这种局面,但应用程序可以。
答案 3 :(得分:-1)
切换功能的一种方法是异常处理。
当抛出异常时,它会将范围返回到catch部分。
但请确保跨函数的内存分配,因为它直接移动到catch blok。
示例代码供参考,
// Example program
#include <iostream>
#include <string>
using namespace std ;
int f1()
{
int *p = (int*) malloc(sizeof(int)) ;
if(p == NULL)
{
throw(1) ;
}
//Code flow continues.
return 0 ;
}
char *g()
{
char *p ;
f1() ;
cout << "Inside fun g*" << endl ;
return p;
}
int f2()
{
g() ;
cout << "Inside fun f2" << endl ;
return 0 ;
}
int main()
{
try
{
f2() ;
}
catch(int a)
{
cout << "Caught memory exception" << endl ;
}
return 0 ;
}