【问题标题】:Using Double Pointers after memory allocated within function在函数内分配内存后使用双指针
【发布时间】:2014-09-10 15:31:31
【问题描述】:

我在 C 中使用双指针,想知道我是否创建了一个初始化表的函数,当我尝试使用 InitStringTable 分配的内存时,它在返回 main 时崩溃。我相信一个简单的解决方法是使 strTable 全局化,然后我相信它可以,但我不喜欢这样做,因为这对我来说更像是一个学习练习,我将表格传递给修改,即我应该能够修改 strTable 从initStringTable 之后的 main 或另一个函数 modifyTable。 感谢您提供的任何帮助。

int main()
{
    char** strTable;

    // Allocates memory for string table.
    InitStringTable(strTable);
    // Below lines should be able to copy strings into newly allocated table.
    // Below lines cause crash however.
    strcpy(strTable[0], "abcdef");

    strcpy(strTable[1], "xy");
}

// Allocates memory for the string table. This function should create a table
// of size 10 strings with each string 50 chars long. The code compiles fine.
void InitStringTable(char** table)
{
   int i = 0;

   table = (char**)malloc(sizeof(char)*10);

   for(i = 0; i < 10; i++)
   {
      table[i] = (char*)malloc(sizeof(char)*50);
   }

   for(i = 0; i < 10; i++)
   {
      memset(table[i], 0, 50);
   }

   strcpy(table[0], "string1");
}

【问题讨论】:

  • 除了你投射malloc(你不应该在C中这样做)的事实之外,这与你应该使用std::stringstd::vector而不是使用原始的C++有什么关系指针?
  • 看来您需要将table = (char**)malloc(sizeof(char)*10); 更改为table = (char**)malloc(sizeof(char*)*10);,因为tablechar * 的数组。
  • 为什么你的函数是无效的?为什么不将返回值用于有用的东西?
  • 间接疯狂...如果您希望InitStringTable 更改作为参数传递的变量,则必须将指针传递给该变量,即:&amp;strTable,这意味着您必须将InitStringTable 更改为char ***table。但实际上:三层间接不是你想要的
  • 是的,这不应该是 C++。我的错。是的,我应该分配 char* 而不是 char。看起来我可以返回 char** 或接受 char*** 来解决我的问题。谢谢。

标签: c pointers


【解决方案1】:

C 是按值传递的。

分配给table 的值在从InitStringTable() 返回时丢失。


在分配指向char 的指针时,还要为指向char 的指针请求空间。

所以这个:

... = (char**)malloc(sizeof(char)*10);

至少应该是(假设 C):

... = malloc(sizeof(char*)*10);

一种可能的方法是:

#include <stdlib.h>
#include <string.h>
#include <errno.h>

int InitStringTable(char *** ppptable, const size_t n, const size_t l)
{
   int result = 0;

   if (NULL == ppptable)
   {
     result = -1;
     errno = EINVAL;
   }
   else
   {
     (*ppptable) = malloc(n * sizeof(**ppptable));
     if (NULL == (*ppptable))
     {
       result = -1;
     }
     else
     {
       size_t i = 0;
       for(; i < n; ++i)
       {
         (*ppptable)[i] = calloc(l, sizeof(*(*ppptable)[i]));
         if (NULL == (*ppptable)[i])
         {
           result = -1; 

           /* Failing in the middle requires clean-up. */
           for (; i > 0; --i)
           {
             free((*ppptable)[i-1]);
           }

           free(*ppptable); 
           (*ppptable) = NULL;

           break;
         }
       }
     }
   }

   return result;
 }

这样称呼它:

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

int InitStringTable(char *** ppptable, const size_t n, const size_t l);

int main(void)
{
  int result = EXIT_SUCCESS;
  char ** strTable = NULL;

  if ( -1 == InitStringTable(&strTable, 10, 42)) //* Allocate array with 10 "strings" à 42 chars. */
  {
    perror("InitStringTable() failed");
    result = EXIT_FAILURE;
  }
  else
  {
    strcpy(strTable[0], "abcdef");
    strcpy(strTable[1], "xy");
  }

  return result;
}

不,我不会讲这种荒谬的“你不想成为三星级程序员!”讨论。

【讨论】:

  • 感谢您的解决方案。是的,我在代码中分配了一个应该是 char* 数组的 char 数组时犯了一个错误。您的解决方案很优雅,因为我忘记在调用 malloc 后添加 NULL 检查。 char *** 可能看起来很有趣,但我认为它有助于强化默认情况下 C 是按值调用的,我在编写这个案例时忘记了这一点。谢谢!
  • 你不必在 main() 结束时释放 strTable[*] 和 strTable,因为它的内存已经用 malloc/calloc 分配了?当在另一个函数中分配内存时,我很难准确理解何时需要空闲指针。
【解决方案2】:

你有一个指针问题。

就像你说:

void inc(int a){
    a++;
}

int main(){
    int a = 0;
    inc(a);
    printf ("%d\n", a); // will display 0, not 1
}

不起作用。

您必须通过 &amp;strTable 而不是 strTable 作为 InitStringTable 参数,并因此更改 InitStringTable 中的其他内容..
或者只是做strTable = InitStringTable(); ,并从InitStringTable 返回一个char**

【讨论】:

  • 呃...为什么没有缩进?
  • 感谢您的解释。
【解决方案3】:

InitStringTable() 下面的行崩溃,因为它们正在尝试执行操作 在与他们不在同一范围内的内存地址上,也没有对
的任何引用 那个内存地址。

函数InitStringTable()为表分配内存,但不能被
调用函数(此处为 main),因为内存对于它所在的函数是本地的
已分配。
因此为了在
中的操作使用相同的内存地址 调用函数,您必须将该地址的引用传递给调用函数。

在您的程序中,您可以按照以下方式进行操作:
将函数声明为:-

char **InitStringTable(char **);


int main()
{
    char** strTable;
    strTable = InitStringTable(strTable);   
    strcpy(strTable[0], "abcdef");   
    strcpy(strTable[1], "xy");
}   

char **InitStringTable(char** table)
{
   int i = 0;

   table = (char**)malloc(sizeof(char)*10);

   for(i = 0; i < 10; i++)
   {
      table[i] = (char*)malloc(sizeof(char)*50);
   }

   for(i = 0; i < 10; i++)
   {
      memset(table[i], 0, 50);
   }

   strcpy(table[0], "string1");


   /* after the function has finished its job, return the address of the table */    
   return table;
}

【讨论】:

  • 也感谢您提供此解决方案。我看到返回 char** 的优点,但我看到有一个 char*** 参数可以进一步理解。
猜你喜欢
  • 2017-12-13
  • 1970-01-01
  • 2019-03-09
  • 2011-01-16
  • 1970-01-01
  • 1970-01-01
  • 2010-09-30
  • 2021-06-22
  • 2015-04-21
相关资源
最近更新 更多