如何正确释放函数返回的结构?

时间:2018-05-02 10:58:18

标签: c c11

我是C的新手,试图找出如何处理结构,从函数返回的引用。

例如,这大致是我想要做的。

typedef struct test_t{
    char *test_c;
} test_t;

int testFunc(test_t** output){
    test_t* testStruct = malloc(sizeof(testStruct));
    char* buf = malloc(sizeof(char)  * 5);
    strcpy(buf, "test");
    testStruct->test_c = buf;
    *output = testStruct;
    return 0;
}

int main() {
    test_t* test;
    testFunc(&test);
    printf("%s\n",test->test_c);
    free(test);
    return 0;
}

所以在main中我得到了测试结构。在printf之后(假设病房后面有一些代码)我不再需要它并且想要解除分配它。但如何正确地做到这一点?我应该首先明确地释放test_c吗?但如果没有分配怎么办?

5 个答案:

答案 0 :(得分:3)

可以像任何其他指针一样释放结构。但是,您必须确保在执行此操作之前释放其所有已分配的成员(如果不这样做,很可能会导致结构成员的内存泄漏)。

typedef struct test_t{
    char *test_c;
} test_t;

int testFunc(test_t** output){
    test_t* testStruct = malloc(sizeof(testStruct));
    char* buf = malloc(sizeof(char)  * 5);
    strcpy(buf, "test");
    testStruct->test_c = buf;
    *output = testStruct;
    return 0;
}

int main() {
    test_t* test;
    testFunc(&test);
    printf("%s\n",test->test_c);
    free(test->test_c);
    free(test);
    return 0;
}

如果你的结构没有分配它的所有元素,你可以将它们的指针设置为NULL,一旦传递给free (3)就等同于什么都不做。

答案 1 :(得分:0)

  

但如何正确地做到这一点?我应该首先明确地释放test_c吗?但如果没有分配呢?

基本经验法则:如果您编写一个分配资源的函数,请编写一个解除分配资源的补充函数。因此,当应用于您的示例时:

void testFree(test_t* toFree) {
    free(toFree->test_c);
    free(toFree);
}

......然后......

printf("%s\n",test->test_c);
testFree(test);

如果testFreetestFunc一起实施并公开,则来电者无需了解您的实施细节。函数本身作为同一个库的一部分,将确保正确维护不变量。如果您切换分配方案,则不需要更改调用代码。您只需修改testFree即可使用新的testFunc并重新链接。

答案 2 :(得分:0)

首先,你需要释放你已经为结构中的char分配的内存,因为你已经初始化了它。否则,您将收到错误,因此在任何自由指令之前,您应该检查保存test_p的内存位置的指针是否正在尝试释放是否为空。此外,自由指令应该将* test作为参数而不是测试。

答案 3 :(得分:0)

  

我应该首先明确地释放test_c吗?

是的,您必须先释放test_c,因为如果您免费test,您将失去对test_c的引用。

  

但如果没有分配呢?

当您从int返回testFunc时,您可以将其用作结构分配的状态(尽管如此,返回指针会更好主意恕我直言):

int testFunc(test_t** output){
    test_t* testStruct = malloc(sizeof(testStruct));
    if (testStruct == NULL)
    /* testStruct allocation failure. */
         return -1;
    char* buf = malloc(sizeof(char)  * 5);
    if (buf == NULL) {
    /* buf allocation failure. */
         free(testStruct);
         return -1;
    }
    strcpy(buf, "test");
    testStruct->test_c = buf;
    *output = testStruct;
    return 0;
}

之后,检查testFunc失败:

/* Check for allocation failure. */
if (testFunc(&test) == -1) {
    fprintf(stderr, "Allocation error");
    exit(EXIT_FAILURE);
}
/* Allocation succeeded. */
printf("%s\n",test->test_c);
free(test->test_c);
free(test)

答案 4 :(得分:0)

您应该有一个分配和初始化test_t实例的过程。在C ++或其他面向对象的语言中,这将是一个构造函数。在C中你必须自己动手 - 类似于以下内容:

test_t *create_test_t(char *init_test_c)
  {
  test_t *tt;

  tt = malloc(sizeof(test_t));
  if(init_test_c != NULL)
    {
    tt->test_c = malloc(strlen(init_test_c)+1);
    strcpy(tt->test_c, init_test_c);
    }
  else
    tt->test_c = NULL;
  }

您还需要一个函数来正确删除test_t实例。类似的东西:

void destroy_test_t(test_t *tt, bool static)
  {
  free(tt->test_c);

  if(!static)
    free(tt);
  }

包含static参数来控制tt是否应该免费。{d}。显然,您不想尝试释放指向test_t的静态实例的指针,在这种情况下,您为static传递TRUE。对于test_t的动态分配实例,例如那些使用create_test_t程序创建的程序,您为static传递FALSE。

每次需要创建或销毁test_t时,都可以使用这些功能。

祝你好运。