BOOLEAN allocate_items(struct item * items,size_t howmany)函数用于分配struct项的数组

时间:2016-10-27 04:28:40

标签: c arrays struct malloc dynamic-memory-allocation

最近,我正在学习C.我在互联网上发现了一个问题。问题是:

  

此功能在内存分配方面有什么问题?   什么是好的解决方案?您可以假设结构项类型具有   已经宣布。这个函数的目的是分配一个数组   struct item,您可以假设在此之前已声明   功能

BOOLEAN allocate_items(struct item * items, size_t howmany)
{ 
   size_t count; 
   items = malloc(sizeof(struct item) * howmany); 

   if(!items) { 
      perror("failed to allocate memory"); 
      return FALSE; 
   }
   return TRUE;

}

所以,我认为第4行是错误的。应该是这样的:

items = malloc(sizeof(struct item));

第6行也错了。应该是这样的:

if(items == NULL){

这是对的吗?

3 个答案:

答案 0 :(得分:1)

首先,正如你所提到的那样,第4行和第6行似乎都没问题。

也就是说,这个函数的基本问题是,你将内存分配给 local 变量范围。这样

  • 因为你没有返回指向已分配内存的指针,在函数返回后,将无法访问已分配的内存。
  • 通过不释放分配的内存,你将面临内存泄漏。

如果必须将内存分配给指针,则需要将该指针的地址传递给该函数并分配内存。您也可以返回指针,但是您需要更改函数签名。

最后,arrays are not pointers and vice-versa。它们可能会出现或类似有时,但它们并不相同。

答案 1 :(得分:-1)

第4行没有错,因为他们试图声明结构数组。 你应该在函数中添加一行来声明一个新的指针temp,以保存项目的当前值,然后在分配内存之后, 第6行应该是

if(items == temp)

检查值是否已更改(因为这是我们最接近检查malloc是否有效)

这是因为!运算符用于检查条件是否为真(至少在大多数语言的基本级别),并且作为指针不是条件或可以用作真或假的int,运算符赢了&#39工作。

答案 2 :(得分:-1)

这是一个固定版本,因为它可能会写在“行业”中。

bool allocate_items(struct item ** pitems, size_t howmany)
{ 
   // argument validation 
   assert(NULL != pitems); // some also add release version checks...
   if(NULL == pitems ) return false;
   // We can also spot memory leak sources here.
   // If *pItems != NULL - does that mean we have to free first to prevent 
   // a leak? What if it is just some random value and not something we can 
   // free? So contract usually is: *pitems has to be NULL...
   assert(NULL == *pitems);
   if(NULL != *pitems) return false;

   // implementation
   *pitems = malloc(sizeof(struct item) * howmany); 

   if(NULL == *pitems) { 
       perror("failed to allocate memory"); 
   }
   return NULL != *pitems;
}

虽然stdbool.h中定义的bool有时会导致C ++互操作出现问题(双方都有相同的符号,但有时sizeof(bool)不同),与发明另一种bool类型相比,它仍然是更好的选择。

pitems是指向应写入新内存块的指针的位置的指针。此函数的调用者可能已写入:

int main(int argc, const char*[] argv) {
    struct item *myBunchOfStuff = NULL;
    if(false != allocate_items( &myBunchOfStuff, 20) ) {
        // ...
        free(myBunchOfStuff);
        myBunchOfStuff = NULL;
    }
    return 0;
}

防御性编程状态:你的功能不能声称“嘿 - 我的功能只因为我的价值不好而崩溃!”。相反,它必须验证自己。它负责崩溃。指针仍然可以!= NULL但其他方面都不好。通常,这个函数不可能捕获。

在C中,每个人都为不要求malloc()的回归值而感到骄傲。在使用C ++编译器编译代码之前,您可以为此感到自豪。然后你必须改变你的代码并修复它。好吧,我想这是一个偏好的问题......

虽然参数检查通常被视为函数实现的一个单独部分,但在此之后,您应该尝试坚持“单点退出”。主要原因是可维护性。有了多个退出点,如果稍后函数变大,如果某些早期退出会忘记释放某些内存或清理其他形式的状态,则更难发现。