处理失败的内存分配
Handling Failed Memory Allocation
这个问题更像是一个完整性检查,而不是 "please solve my problem"。我最近继承了一个应用程序的一些代码,该应用程序由许多具有不同技能的不同开发人员编写了几十年。因此,试图理解代码实际想要做什么本身就是一项使命。
无论如何,我一次又一次地遇到这种动态分配内存的初始化模式,并且很快就检查了结果。因为这段代码同时存在于独立库和 GUI 中,所以之前的开发人员使用 _STANDALONE
宏来检查它并相应地处理错误:
double *myArray = (double *) calloc(length, sizeof(double));
if (myArray == NULL)
{
strcat(message1, "myArray");
#ifdef _STANDALONE
fprintf(stderr, "%s %s\n", message1, message2);
#else
MessageBox(Window, message1, message2, MB_ICONEXCLAMATION);
#endif
exit(EXIT_FAILURE);
}
注意:您可以假设 message1
和 message2
包含一个字符串 "failed to allocate memory for varible..." 并且足够大,可以附加额外的 gubbins。
完整性检查来了。内存分配失败的最可能原因是操作系统没有任何备用内存。让我们看一下错误处理代码,如果我们假设没有更多的内存空闲:
fprintf
可能会或可能不会失败,具体取决于内部缓冲区的状态。我不知道引擎盖下的功能是什么样的,但我假设它的内存需求很小。
- 我很确定调用
MessageBox
会导致额外的内存分配,因为这会导致 GUI 对象显示在屏幕上。因此,这肯定会失败,因此无法实现开发人员的意图。
简而言之,我建议可以更好地处理这个问题,但正确的路径并不那么明显。
仅仅因为 calloc
失败并不意味着错误处理路径也会失败。
calloc
可能因为请求荒谬而失败。例如,如果 length * sizeof (double)
溢出,calloc
应该失败。或者即使没有溢出,请求一开始也是不合理的内存量。在这些情况下,fprintf
或 MessageBox
.
可能有足够的可用内存
在不知道 fprintf
和 MessageBox
的实现的情况下,您无法确定它们是否需要额外的内存分配。可能系统已经为他们预留了一些内存,目的是为了在内存不足的情况下显示错误信息。
我不担心 fprintf
和 MessageBox
失败。如果您的系统确实没有足够的空闲内存来处理 fprintf
或 MessageBox
,它可能会以其他许多方式崩溃。面对如此极端的内存压力而终止是非常合理的。
这里的大问题是 "length" 的典型大小。如果长度通常非常高(比如 1MB 及以上),可以很安全地假设即使分配失败,您仍然有足够的内存用于简单的消息框。 (检查的实际目标是防止这些非常大的分配)。
如果数组通常很小,最好不要显示任何框。 (您可以做的是预先分配所有必要的资源以显示 window。但不确定消息框是否可行)。
解决这个问题的一种方法是预先分配一些永远不会被使用的内存。
当你 运行 内存不足时,你 free
这个区域,所以希望你的错误处理程序有足够的内存来完成它的工作。
这个问题更像是一个完整性检查,而不是 "please solve my problem"。我最近继承了一个应用程序的一些代码,该应用程序由许多具有不同技能的不同开发人员编写了几十年。因此,试图理解代码实际想要做什么本身就是一项使命。
无论如何,我一次又一次地遇到这种动态分配内存的初始化模式,并且很快就检查了结果。因为这段代码同时存在于独立库和 GUI 中,所以之前的开发人员使用 _STANDALONE
宏来检查它并相应地处理错误:
double *myArray = (double *) calloc(length, sizeof(double));
if (myArray == NULL)
{
strcat(message1, "myArray");
#ifdef _STANDALONE
fprintf(stderr, "%s %s\n", message1, message2);
#else
MessageBox(Window, message1, message2, MB_ICONEXCLAMATION);
#endif
exit(EXIT_FAILURE);
}
注意:您可以假设 message1
和 message2
包含一个字符串 "failed to allocate memory for varible..." 并且足够大,可以附加额外的 gubbins。
完整性检查来了。内存分配失败的最可能原因是操作系统没有任何备用内存。让我们看一下错误处理代码,如果我们假设没有更多的内存空闲:
fprintf
可能会或可能不会失败,具体取决于内部缓冲区的状态。我不知道引擎盖下的功能是什么样的,但我假设它的内存需求很小。- 我很确定调用
MessageBox
会导致额外的内存分配,因为这会导致 GUI 对象显示在屏幕上。因此,这肯定会失败,因此无法实现开发人员的意图。
简而言之,我建议可以更好地处理这个问题,但正确的路径并不那么明显。
仅仅因为 calloc
失败并不意味着错误处理路径也会失败。
calloc
可能因为请求荒谬而失败。例如,如果length * sizeof (double)
溢出,calloc
应该失败。或者即使没有溢出,请求一开始也是不合理的内存量。在这些情况下,fprintf
或MessageBox
. 可能有足够的可用内存
在不知道
fprintf
和MessageBox
的实现的情况下,您无法确定它们是否需要额外的内存分配。可能系统已经为他们预留了一些内存,目的是为了在内存不足的情况下显示错误信息。
我不担心 fprintf
和 MessageBox
失败。如果您的系统确实没有足够的空闲内存来处理 fprintf
或 MessageBox
,它可能会以其他许多方式崩溃。面对如此极端的内存压力而终止是非常合理的。
这里的大问题是 "length" 的典型大小。如果长度通常非常高(比如 1MB 及以上),可以很安全地假设即使分配失败,您仍然有足够的内存用于简单的消息框。 (检查的实际目标是防止这些非常大的分配)。
如果数组通常很小,最好不要显示任何框。 (您可以做的是预先分配所有必要的资源以显示 window。但不确定消息框是否可行)。
解决这个问题的一种方法是预先分配一些永远不会被使用的内存。
当你 运行 内存不足时,你 free
这个区域,所以希望你的错误处理程序有足够的内存来完成它的工作。