C中的析构函数/回调用于获取shared_ptr行为

时间:2011-05-17 12:15:45

标签: c destructor

我正在用C编写套接字监听器。每当它接受时,它就会创建一个新线程(分离)来恢复数据和进程。

但每次,我都需要手动调用close(socket_descriptor)。如果是C ++,我可以选择在析构函数中关闭它。

我试图找出能给我提供相同行为的东西 基本上,我想在C中创建类似shared_ptr的东西。

在C中是否有人可以在物体超出范围时获得信号或通知?

3 个答案:

答案 0 :(得分:3)

不,这不是C的固有特性......要启用类似于你所要求的东西,你必须创建某种回调机制,使用查找表来匹配一个对象它的“destrutor”,并在您编写的每个函数的末尾调用该通用回调函数,或者更有可能在声明对象的每个作用域的末尾调用。我认为这非常混乱和复杂,最后,这可能比它的价值更麻烦,也就是说,你可以简单地使用goto并在函数末尾写下所有清理代码(我知道一般使用goto被认为是非常糟糕的风格,但是为了在函数结束时跳转到清理代码,它们实际上可以使代码比保留的代码更清晰每次出现错误时重复相同的清理代码。)

例如,假设您有一个函数分配了一些内存并在函数的某个早期点打开了文件描述符,但是如果有一些错误,则无法继续......您不能简单地返回错误代码,你必须做一些清理,但在代码中间反复重复清理代码会很痛苦:

int my_function()
{
    int* array_on_heap = malloc(ARRAYSIZE * sizeof(int));
    int file_descriptor;

    //...some code

    if (some_ptr == NULL)
        goto error_cleanup;

    //...some more code

    if (some_other_pointer != some_ptr)
        goto error_cleanup;

    //...even more code

    //normal return with no error
    return 0;

    error_cleanup:
        //clean-up code in case there was an error
        free(array_on_heap);
        close(fd);
        return -1;
}

这里谨慎而明智地使用goto创建了一个非常简洁的功能区域,可以进行破坏和清理,您不必担心可能缺少清理功能你决定在功能本身的实际“机制”中撒上清理代码。

答案 1 :(得分:1)

普通老C中没有自动析构函数。你有没有考虑通过垃圾收集器来做这件事?

例如,您可以使用Boehm-Demers-Weiser conservative garbage collector分配对象,然后在对象无法访问时调用GC_REGISTER_FINALIZER关闭套接字描述符。

另一个解决方案是将客户端的回调函数包装到另一个函数中,该函数只调用回调然后关闭套接字。这样您就不必在每个回调函数中显式关闭它。

答案 2 :(得分:0)

在“原始”C中只有一种方法:

void abc_init (parameters);

void abc_cleanup (parameters);

其中所有abc函数都属于模块abc,它由abc.h和abc.c组成。然后,对象的分配可以由调用者处理到abc模块,也可以由模块本身处理:

// alternative 1, leave allocation to the caller

#include "abc.h"

int main()
{
  Abc_t x;

  abc_init(&x);

  ...

  abc_cleanup(&x);
}


// alternative 2, the module handles allocation

// abc.c

static Abc_t* x;

void abc_init (parameters)
{
  x = some_sort_of_allocation();
  set x based on parameters
}


...

void abc_cleanup (parameters)
{
  cleanup x
}