是否有可能在纯C中实现RAII?
我认为不可能以任何理智的方式,但也许可能使用某种肮脏的技巧.重载标准free
函数会想到或者可能覆盖堆栈上的返回地址,这样当函数返回时,它会调用一些其他函数以某种方式释放资源?或者也许有一些setjmp/longjmp技巧?
这纯粹是学术上的兴趣,我无意写出这种不可移植和疯狂的代码,但我想知道这是否可能.
Joh*_*itb 76
这是固有的实现依赖,因为标准不包括这种可能性.对于GCC,cleanup
当变量超出范围时,该属性会运行一个函数:
#include <stdio.h>
void scoped(int * pvariable) {
printf("variable (%d) goes out of scope\n", *pvariable);
}
int main(void) {
printf("before scope\n");
{
int watched __attribute__((cleanup (scoped)));
watched = 42;
}
printf("after scope\n");
}
Run Code Online (Sandbox Code Playgroud)
打印:
before scope
variable (42) goes out of scope
after scope
Run Code Online (Sandbox Code Playgroud)
看到这里
Kel*_*yne 11
将RAII引入C(当你没有cleanup()
)的一个解决方案是使用将执行清理的代码包装你的函数调用.这也可以打包在一个整洁的宏(最后显示).
/* Publicly known method */
void SomeFunction() {
/* Create raii object, which holds records of object pointers and a
destruction method for that object (or null if not needed). */
Raii raii;
RaiiCreate(&raii);
/* Call function implementation */
SomeFunctionImpl(&raii);
/* This method calls the destruction code for each object. */
RaiiDestroyAll(&raii);
}
/* Hidden method that carries out implementation. */
void SomeFunctionImpl(Raii *raii) {
MyStruct *object;
MyStruct *eventually_destroyed_object;
int *pretend_value;
/* Create a MyStruct object, passing the destruction method for
MyStruct objects. */
object = RaiiAdd(raii, MyStructCreate(), MyStructDestroy);
/* Create a MyStruct object (adding it to raii), which will later
be removed before returning. */
eventually_destroyed_object = RaiiAdd(raii,
MyStructCreate(), MyStructDestroy);
/* Create an int, passing a null destruction method. */
pretend_value = RaiiAdd(raii, malloc(sizeof(int)), 0);
/* ... implementation ... */
/* Destroy object (calling destruction method). */
RaiiDestroy(raii, eventually_destroyed_object);
/* or ... */
RaiiForgetAbout(raii, eventually_destroyed_object);
}
Run Code Online (Sandbox Code Playgroud)
您可以SomeFunction
使用宏来表示所有锅炉板代码,因为每次调用都是相同的.
例如:
/* Declares Matrix * MatrixMultiply(Matrix * first, Matrix * second, Network * network) */
RTN_RAII(Matrix *, MatrixMultiply, Matrix *, first, Matrix *, second, Network *, network, {
Processor *processor = RaiiAdd(raii, ProcessorCreate(), ProcessorDestroy);
Matrix *result = MatrixCreate();
processor->multiply(result, first, second);
return processor;
});
void SomeOtherCode(...) {
/* ... */
Matrix * result = MatrixMultiply(first, second, network);
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
注意:你想要使用像P99这样的高级宏框架来制作类似上面的东西.
如果您的编译器支持C99(或者甚至是其中很大一部分),您可以使用可变长度数组(VLA),例如:
int f(int x) {
int vla[x];
// ...
}
Run Code Online (Sandbox Code Playgroud)
如果内存服务,gcc在添加到C99之前已经/支持了这个功能.这(大致)相当于以下简单情况:
int f(int x) {
int *vla=malloc(sizeof(int) *x);
/* ... */
free vla;
}
Run Code Online (Sandbox Code Playgroud)
但是,它不允许您执行dtor可以执行的任何其他操作,例如关闭文件,数据库连接等.
归档时间: |
|
查看次数: |
11350 次 |
最近记录: |