使用malloc()获取唯一指针

时间:2010-08-07 01:46:31

标签: c pointers malloc

所以,我有一些函数返回指针,或者NULL出错。现在我想为不同的错误/条件添加另一个可能的值。我之前在其他一些答案中听到了这一点 - 使用malloc()创建一个唯一的指针,它将作为返回此类函数的可能值(所以现在可以返回一个正确的指针,NULL或{ {1}}您可以确定0xWhatever不会用于其他任何内容)。所以,自然0xWhatever可能是一个安全的赌注,但我想知道malloc(1)是否也是安全的。 malloc(0)地址是否可能用于其他地方?有人可以澄清一下这种技术应该如何运作,也许可以说是什么?

6 个答案:

答案 0 :(得分:5)

来自C99标准:

  

如果请求的空间大小为零,则行为是实现定义的:返回空指针,或者行为就像大小是非零值一样,但返回的指针不应用于访问一个对象。

最好使用malloc(1)。如果内存可用,则保证返回非NULL。

答案 1 :(得分:3)

为此目的使用malloc是一种非常糟糕的做法。只需:

static const char myerror;
return (void *)&myerror;

得到一个“错误值”指针,该指针永远不会与指向程序其余部分的任何真实对象的指针进行比较。

编辑:最初我遗漏了&。固定的。

答案 2 :(得分:2)

我的理解是,一般来说,malloc(0)将“分配”以后仍应释放的内存。它会给你一个你不应该写的内存位置。

您不一定要使用malloc()来获取唯一地址,例如,它可能来自静态位置。然后你可以使用这个地址作为你的另一个条件。同样也省略了分配。我不记得这个用法的术语,关于代理的东西。

#define ERRORPTR ((void *)&_unusedvar)
static char _unusedvar;

if ( /* failed */ )
    return ERRORPTR;

答案 3 :(得分:2)

与问题有些相似,但是有一个“错误条件指针”(除了NULL)实际上不是惯用的C.如果你想编写一个为指针分配内存并且可以返回几个不同错误条件的函数,还有两种常用的方法:

  1. 设置errno以描述您的特定错误,并针对所有错误返回NULL
  2. 将指针指针作为参数,并返回整数错误代码
  3. E.g。

    sometype* my_function()
    {
      sometype* p; 
    
      /* Do something */
    
      if (error_1_occurred) {
         errno = EAGAIN; /* Or whatever is appropriate */
         return NULL;
      } else if (error_2_occurred) {
         errno = EINVAL; /* Or whatever is appropriate */
         return NULL;
      } 
    
      p = malloc(/* whatever */);
    
      /* Do stuff */
    
      return p;
    }
    

    int my_function(sometype** pp) {
    
      if (!pp) return -99;
    
      /* Do something */
    
      if (error_1_occurred) {
         return -1;
      } else if (error_2_occurred) {
         return -2;
      } 
    
      *pp = malloc(/* whatever */);
    
      /* Do stuff */
    
      return 0;
    }
    

答案 4 :(得分:1)

直到并且我相信包括C89在内,其含义尚未明确。标准对于非零(或更差,负面)大小没有什么可说的。我有理由相信它现在是实现定义的。使用非零大小来实现可移植性。

您可以通过使用某个全局变量或静态变量的地址作为哨兵来回避问题,也许使用合适的演员。

另一种传统方法(在最早版本的signal()中使用,IIRC)是将0以外的小整数转换为指针类型。这实际上是相对不可移植的,因为可移植且安全地转换为指针的唯一整数是0,即NULL。

请注意,无论是否分配,您都需要小心,不要试图实际释放您的标记指针。

答案 5 :(得分:1)

NULL指针只是指向内存位置whit地址0的指针,因为内存通常以4k块的形式分页,你可以使用1到4095之间的数字来返回函数中的其他类型的错误因为不会为您的应用程序分页内存(0 - 4096)(除非您使用mmap明确映射它)。

所以做以下事情是安全的:

if(someError)

  return NULL;

else if(someOtherError)

  return (void *)1;

else
  /* Do something else */