【问题标题】:Struct pointer remains NULL even after assignment即使在分配之后,结构指针仍然为 NULL
【发布时间】:2018-05-14 21:54:25
【问题描述】:

我正在尝试从函数返回一个 Tuple 结构,但它似乎没有更新分配给它的指针。

例如,如果我在返回元组之前查看它的值,我发现它被正确分配:

342        Tuple *t = create_tuple();
(gdb) 
345        memcpy(t->part1, cwd, i + 1);
(gdb) p t
$5 = (Tuple *) 0x605010
(gdb) n
346        memcpy(t->part2, &cwd[i + 1], cwd_len - i - 1);
(gdb) 
348        return t;

但是在它被分配之后,我分配给它的元组指针看起来仍然是 NULL:

291              if ((partitioned = split_prefix(cwd, strlen(cwd))) == NULL)
(gdb) p partitioned
$11 = (Tuple *) 0x0
(gdb) n
296              memcpy(name_field, partitioned->part1, strlen(partitioned- 
>part1));
(gdb) p partitioned
$12 = (Tuple *) 0x0

我认为既然我返回了不是 NULL 的指针,它应该没问题,所以我对如何在调用前后使用 NULL 指针感到困惑。也许是我错误地初始化了指针?

这是结构体指针返回的函数:

// gets name field and returns TRUE if successful, otherwise FALSE
int get_name_field(Tuple *partitioned, char name_field[], char *fname, char *cwd, int cwd_len)
{
   // fname cannot be broken up
   if (strlen(fname) > 155)
   {
      perror(fname);
      return FALSE;
   }
   // there is a path (prefix)
   else if (cwd)
   {
      // fname field isn't long enough
      if (strlen(cwd) + 1 + strlen(fname) > 100)
      {
         // ***********assignment here**************
         if ((partitioned = split_prefix(cwd, strlen(cwd))) == NULL)
         {
            perror("partition failed");
            return FALSE;
         }
         memcpy(name_field, partitioned->part1, strlen(partitioned->part1));
      }
...

返回元组指针的函数:

// return a the part of prefix that fits in name field, and the remainder
// if no delimiter is found, returns null
Tuple *split_prefix(char *cwd, int cwd_len)
{
   // find last '/' delimiter that is within NAME_LEN range 
   int found = 0;
   int i = cwd_len <= 100 ? cwd_len - 1: NAME_LEN;
   for (; i > -1; i--)
   {
      if (cwd[i] == '/')
      {
         found = TRUE;
         break;
      }
   }

   // no delimiter found 
   if (!found)
   {
      return NULL;
   }
   // too long to be stored in overflow
   else if (cwd_len - i > PREFIX_LEN)
   {
      return NULL;
   }

   // **********Tuple created here************
   Tuple *t = create_tuple();

   // make partitions
   memcpy(t->part1, cwd, i + 1);
   memcpy(t->part2, &cwd[i + 1], cwd_len - i - 1);

   return t;
}

元组的定义:

#define NAME_LEN 100
#define PREFIX_LEN 155

// holds partioned strings of prefix
typedef struct Tuple
{
   char part1[NAME_LEN];
   char part2[PREFIX_LEN];
} Tuple;

创建元组:

// create a tuple with default values
Tuple *create_tuple(void)
{
   Tuple *t = malloc(sizeof(Tuple));
   memset(t->part1, '\0', NAME_LEN);
   memset(t->part2, '\0', PREFIX_LEN);

   return t;
}

编辑:调用get_name_field的函数:

void test_get_name_field3(void)
{
   Tuple *partitioned = NULL;
   char name_field[NAME_LEN] = {'\0'};
   char *fname = "hellobutunfortunatelythiswon'tfit.txt";
   char *cwd = "user/bin/arafian/ratherlongdirectorynameandwillnot/fitin"
               "thenamefieldonlysoitwilloverflowtotheprefixfield";
   int cwd_len = strlen(cwd);

   get_name_field(partitioned, name_field, fname, cwd, cwd_len);
   char *result = "user/bin/arafian/ratherlongdirectorynameandwillnot/";
   checkit_string(name_field, result);
   free(partitioned);
}

【问题讨论】:

  • 不看你的代码,对 gdb 输出持怀疑态度,它以前对我撒过谎(好吧,gdb + gdbserver)。或许可以输入一些printfs 来验证 gdb 告诉你的完全有理由把头撞到墙上。
  • 请发布 MCVE。 NAME_LEN 和 PREFIX_LEN 是什么? split_prefix 函数可能会超出范围。调用代码执行strlen(partitioned-&gt;part1),但尚不清楚split_prefix 是否终止part1
  • @M.M 我添加了常量。 part1 和 part2 都应该以 null 结尾,因为 create_tuple 将两个数组都分配为以所有 null 字符开头。至少那是我试图做的。
  • 我建议始终使用您的长度宏,而不是在代码中混合使用宏和幻数。 (或者最好在有问题的数组上使用sizeof
  • 解除对空指针的引用是未定义的行为,这意味着任何事情都可能发生。你不应该期待一个段错误或任何其他特定的事情

标签: c return


【解决方案1】:

如果你想通过一个函数的参数返回一个指针,那么该函数必须接受一个双指针作为参数。 IE。 int get_name_field(Tuple **partition, ...) { 并像 get_name_field(&amp;partition, ...) 一样调用。

这与我最近在这里回答的问题 https://stackoverflow.com/a/50261485/982257 和可能还有其他几个问题完全相同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-31
    • 1970-01-01
    • 2021-09-05
    • 2015-01-12
    • 2019-09-23
    相关资源
    最近更新 更多