【问题标题】:Significance of double pointer and triple pointer in this code snippet此代码片段中双指针和三指针的意义
【发布时间】:2014-12-03 12:18:24
【问题描述】:
#include<stdio.h>
#include<stdlib.h>
void add(char **p);
void print(char **p);
int cnt=0;
main()
{
  int option;
  char **p=NULL;
while(1)
{
  printf("------MENU-----\n");
  printf("1>input\n 2>print\n3>exit\n");
  printf("enter ur choice\n");
  scanf("%d",&option);getchar();
 switch(option)
 {
    case 1: add(p);
            break;
    case 2: print(p);
            break;
   case 3: return;
   default: printf("Invalid option\n");

 }
}
}
void add(char **p)
{
  int i;
  p=(char**)realloc(p,(cnt+1)*sizeof(char*));
  if(p==NULL)
  {
        printf("Error: memory not available\n");
        return;

  }
  p[cnt]=NULL;
  p[cnt]=(char*)realloc(p[cnt],20*sizeof(char));

  puts("enter a name");
  gets(p[cnt]);
  cnt++;
  printf("cnt=%d\n",cnt);
}
void print(char **p)
{
  int i;
  for(i=0;i<cnt;i++)
  printf("p[%d]=%s\n",i,p[i]);
}

在上面的代码中,我正在创建一个名称数据库。为此,我使用动态内存分配。我正在使用指针数组方法为二维数组分配内存。当我在 gcc 编译器 上执行这个程序时,我得到 segmentation fault。我不明白为什么会这样?你能告诉我错误在哪里吗?

【问题讨论】:

  • 除了下面的答案中已经提到的关于变量 p 在函数 add 中的本地化之外,我很确定您必须首先初始化 p = malloc(...),因为函数realloc 期望(作为输入参数)指向先前使用 mallocrealloc 分配的内存段的指针。
  • 一些提示:使用调试器,一致地缩进你的代码,避免gets,不要转换malloc/realloc的返回值,sizeof(char)总是1。
  • @barakmanos:我的 C 标准说“如果 ptr 是空指针,则 realloc 函数的行为类似于 malloc 函数。”但是,如果在没有事先 add 的情况下调用 print,则指针为 0。
  • @barakmanos - realloc 可以做到mallocfree 可以做到的一切(包括初始分配)。这是从不使用realloc 而不是从不使用mallocfree 的论据!设计realloc 的人都忘记了“做一件事并做好”作为设计原则。
  • @AAT realloc() 可以将内存的内容“复制”到另一个新的逻辑位置,而无需更改物理地址,因为它知道源将被释放。因此不需要出现memcpy()malloc()free() 将如何执行这种高效的重新分配?

标签: c dynamic-memory-allocation realloc


【解决方案1】:

在main中,你所做的只是分配p = NULL,然后在print中使用这个NULL指针,这会导致段错误。请注意,add(p) 等效于 add(NULL),并且不会更改 p。 您的意思是通过add(&amp;p) 传递地址吗?如果是这样,您需要稍微调整一下* 的数量。

【讨论】:

    【解决方案2】:

    main中的p按值交给add。然后add 修改本地副本,而不是原始p

    除了糟糕的格式以及将指向mainp 的指针传递给add 所需的一切:

    ...
    
      case 1: add(&p);
    ...
    
    void add(char ***p)
    {
      int i;
      *p = realloc(*p,(cnt+1)*sizeof(char*));
      if(*p==NULL)
      {
            printf("Error: memory not available\n");
            return;
    
      }
      (*p)[cnt]=NULL;
      (*p)[cnt]=realloc((*p)[cnt],20*sizeof(char));
    
      puts("enter a name");
      gets((*p)[cnt]);
      cnt++;
      printf("cnt=%d\n",cnt);
    }
    

    【讨论】:

      【解决方案3】:

      在 add 函数中创建了一个 2D 指针 p 的副本,更新这个指针不会反映在 main 函数中。 解决此问题的一个快速方法是从 add 函数返回 2D 指针“p”。

      char** print(char **p)
      {
          ....
          ....
          return p;
      }
      

      【讨论】:

        【解决方案4】:

        通过引用传递。您需要传递指针的地址以确保函数add() 中的更改反映在main() 中。避免使用gets()

        在这种情况下

        add(&p);
        

        因此,您的 add() 函数定义应更改以处理此问题。 或者另一种方法是让 add 函数进行所需的分配并将该地址返回给您的指针

        char **add();
        

        检查下面的代码:

        char  **add(char **p)
        {
          int i;
          p=(char**)realloc(p,(cnt+1)*sizeof(char*));
          if(p==NULL)
          {
                printf("Error: memory not available\n");
                return;
        
          }
          p[cnt]=NULL;
          p[cnt]=(char*)realloc(p[cnt],20*sizeof(char));
        
          scanf("%s",p[cnt]);
          cnt++;
          printf("cnt=%d\n",cnt);
          return p;
        }
        

        所以你的电话应该是:

        p = add(p);
        

        【讨论】:

          【解决方案5】:

          除此之外,我认为没有人提到realloc 重新分配失败的陷阱。假设这个调用

          p=(char**)realloc(p,(cnt+1)*sizeof(char*));
          

          未能分配新内存:然后会发生什么?是的,您将得到NULL 返回:但是已分配 并且p 指向的内存不会 得到free'd。即时内存泄漏。

          必须像这样致电realloc

          char* pTemp = realloc(p, cnt + 1);
          if(pTemp != NULL)
          {
              p = pTemp;             // Now safe to update p
          }
          else
          {
              // Error handling as required, possibly including freeing p
          }
          

          另一个使用realloc的原因。恕我直言,您自己做缓冲区复制并没有真正的过分。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-01-08
            • 2016-12-23
            • 2020-12-01
            • 2021-12-16
            • 2019-11-29
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多