在 c 中动态分配内存时,是否应该同时使用 if 和 else 条件?

Should I use both if and else conditions when dynamically allocating memory in c?

int main(){
    
int* index = (int*)malloc(n*sizeof(int));
        
if(index == NULL){
     printf("Memory Not Allocated.\n");
     exit(0);
}
        
int* arr = (int*)malloc(p*sizeof(int));
        
if(arr == NULL){
     printf("Memory Not Allocated.\n");
     exit(0);
}

int* queue = (int*)malloc(frames*sizeof(int));
        
if(queue == NULL){
     printf("Memory Not Allocated.\n");
     exit(0);
}

more codes...
---------------
---------------
more codes....

}

这是我程序的一部分。在这段代码中,我为索引、arr 和队列动态分配了内存。我还使用了 if 条件来检查内存是否已分配。我只用了部分。我没有使用 else 部分,因为我在 if 条件中使用了 exit(0) 。这种方式是否正确?或者我还应该像下面那样使用其他部分吗?

int main(){
        
int* index = (int*)malloc(n*sizeof(int));
            
if(index == NULL){
     printf("Memory Not Allocated.\n");
     exit(0);
}else{
            
    int* arr = (int*)malloc(p*sizeof(int));
            
    if(arr == NULL){
         printf("Memory Not Allocated.\n");
         exit(0);

    }else{

         int* queue = (int*)malloc(frames*sizeof(int));
        
         if(queue == NULL){
              printf("Memory Not Allocated.\n");
              exit(0);

         }else{

              more codes...
              ---------------
              ---------------
              more codes....
         }
    }     
}

我想如果内存因为 exit(0) 而没有分配,程序就会退出。因此,没有必要使用 else 部分。这是我的看法。

什么是正确且更好的方法?这两种方式都可以用吗?

非常感谢您的帮助

As I suppose program will exit if the memory is not allocated because of exit(0). Therefore, it's not necessary to use else part.

是的,没错。 else 不是必需的,使用 else 会使代码更难阅读。所以应该使用。

我会使用的方法如下:

#include <stdio.h>
#include <stdlib.h>

int main(void) 
{
    int *index = malloc(n*sizeof(int));
    int *arr   = malloc(p*sizeof(int));
    int *queue = malloc(frames*sizeof(int));

    if (index == NULL || arr == NULL || queue == NULL) {
        printf("Memory Not Allocated.\n");
        free(index);
        free(arr);
        free(queue);
        exit(EXIT_FAILURE);
    }

    more codes...
    ---------------
    ---------------
    more codes....
}

注意事项:

  1. 在 C 中,您应该 转换 malloc 的 return 值。有关详细信息,请参阅 this question
  2. 您可以推迟错误检查,直到分配完所有内存。预期所有分配都会成功。万一一个或多个分配失败,代码会在给用户坏消息之前浪费一点时间。但除此之外,尝试所有分配也没有坏处。用户不太可能注意到额外的时间,并且会更关心程序没有 运行.
  3. 尝试分配所有内存后,您可以使用单个 if 检查是否所有分配都成功。
  4. C 标准明确允许将 NULL 指针传递给 free,因此只要您初始化了每个指针(使用有效地址或 NULL),您就可以传递每个指向 free 的指针(无需检查它是否为 NULL)。
  5. exit(0)用于通知shell程序成功。使用 non-zero 值(通常为 1)调用 exit 表示失败。 <stdlib.h> 中的宏 EXIT_FAILURE 是官方的 non-zero 值,应传递给 exit 以指示失败。

三种情况下“else”都是多余的。实际上,由于它们之间没有依赖关系,因此创建决策树会有些混乱。一个小细节。比较NULL == variable 而不是(variable == NULL) 因为当我们进行击键时错误的是“=”而不是正确的“==”。最后,让每条错误信息都独一无二!在较大的程序中,这极大地有助于调试和技术支持。

除非你写的是一个简单的程序,否则应该避免在你的程序的顶层使用独立的 bear bones mallocs。

现在看来,我似乎要超出你的问题范围,但事实上,你的问题回避了更广泛的答案,因为要做出最好的编程,我们必须始终意识到我们尖锐、狭隘的关注点适合更大的事物方案,这就是我想要解决的问题。

处理 mallocs 时首先要考虑的是内存泄漏。通过确保在失败时它们被释放,您在该问题的第一部分做得很好。请注意,未来还有其他几个问题。

使用 mallocs 的最大和最常见的问题是很容易导致内存泄漏。同样,我不能过分强调这一点。这应该是您每次使用 mallocs 时最关心的问题。

与这个头号问题相比,分支风格,只要它是结构化的,并且你已经努力保持干净和直接,对于内存泄漏的处理来说是次要的。 (例如,英国口音和爱尔兰口音一样好,说话好一点更重要,但远不如你是否有犯罪行为重要。)

有很多好的方法来处理好的malloc写法。

例如,只要您不处理中断事件或其他高级错误处理问题,让我们看看使用 mallocs 的好方法。

  1. 使您的程序严格结构化。
  2. 编写分配程序,成对地为 malloc 做所有正确的事情。一个过程为一组特定场景分配内存,另一个过程将以完全相反的方式为同一组场景释放完全相同的内存。这些可以用多种方式编写。但同样,完美地完成工作是最重要的。一旦你调试了程序,你就不必担心它是否正确完成,因为你会知道的。这一小块知识对于您如何使用这些过程来说是无价的。您希望能够依靠他们。
  3. 在你的程序中拓扑结构,确保在分配内存的任何点,分配后的每条执行路径都会在某个点执行相应的释放过程,而不管所有条件和循环。
  4. 现在你写了一套很好的程序,你可以把它们拿出来应用到更高级的 mallocing 方面。

您希望将这些成对的过程设计得足够好,以至于您知道在正确执行这两个过程之后,仍然没有分配与这对事务关联的内存。同样,风格有一定的重要性,但是有很多方法可以编写这些,真正重要的是确保没有内存泄漏这一突出事实。这是最重要的。

这是一个不错的小故事。有一次我签了一份合同,当我来到现场时,一个严重的内存泄漏问题已经持续了几个月,而且还没有得到解决。我使用了我向您描述的方法,并在一天之内完成了整个程序并构建了所有 malloc。

几天后问题再次发生。我知道那不可能,因为我已经检查了程序中的所有结构化路径,但事实就是如此。因为系统地应用了配对 malloc 的简单原则并遵循程序的拓扑流程,我知道它是正确的,所以我知道去别处看看是有意义的。经过一些分析,我认为唯一的可能性是复合中断触及了破坏程序结构的相同内存位置。所以我设置了几个断点,如果出现问题就会触发,果然我成功了。

我查看了堆栈,果然,一个中断篡改了内存分配,另一个踩到了它。确定了这两个事件后,我只是在这两个事件之间添加了互斥。这从开始到结束大约花了 10 分钟,解决了几个月的问题。

如果不以系统的方式以正确的方式执行我的 malloc,我不可能找到问题。顺便说一句,我不知道我在条件句中使用了什么风格,这并不重要。做到了吗?