如何禁用对不透明变量的整数赋值 (0)?
我有一个模块,我想对其客户端隐藏其实现。
我选择声明一个不透明类型,它实际上是一个指向仅在实现中定义的结构的指针。
一切都工作正常,除了我可以将零值分配给这种类型的变量,这是我想避免的。
中的示例
这是 C头文件 foo.h
/* foo.h */
typedef struct foo *foo_t; /* <- sorry this was obviously flawed, the '*' was missing */
extern void foo_create( foo_t *t );
extern void foo_destroy( foo_t *t );
extern void foo_tile( foo_t x );
实现文件 foo.c
/* foo.c */
#include <stdlib.h>
#include "foo.h"
struct foo {
int some_member;
};
void foo_create( foo_t *t )
{
if ( *t==0 ) {
*t = malloc( sizeof(struct foo) );
}
}
void foo_destroy( foo_t *t )
{
if ( *t!=0 ) {
free(*t);
*t = 0;
}
}
void foo_tile( foo_t t )
{
t->some_member++;
}
现在这是使用该模块的示例客户端: bar.c:
#include "foo.h"
int main( int argc , char **argv )
{
foo_t toe;
foo_create( &toe );
toe = 0; /* <-- How to make the compiler (gcc) refuse this? */
toe = 1; /* <--- the compiler rejects this YAY!! */
}
不透明类型实际上是一个指向动态分配结构的指针; 如果我将值 0 赋给它,则会导致内存泄漏,如果编译器拒绝将 0 赋给该不透明指针,则可以避免这种情况。
编译器不接受将非空值分配给指针,因此我认为通过多一点努力也可以实现零值。
是否可以禁用此分配?我怎样才能做到这一点? 如果需要使用一些 C++ 或 gcc 特定的构造,我会同意,尽管纯 C 解决方案会很好。
提前致谢。
I have a module whose implementation I want to hide from its clients.
I chose to declare an opaque type which is actually a pointer to structure to be defined only in the implementation.
It all is working fine, except that I can assign the zero value to a variable of this type, which I want to avoid.
Here's an example in C.
header file foo.h
/* foo.h */
typedef struct foo *foo_t; /* <- sorry this was obviously flawed, the '*' was missing */
extern void foo_create( foo_t *t );
extern void foo_destroy( foo_t *t );
extern void foo_tile( foo_t x );
implementation file foo.c
/* foo.c */
#include <stdlib.h>
#include "foo.h"
struct foo {
int some_member;
};
void foo_create( foo_t *t )
{
if ( *t==0 ) {
*t = malloc( sizeof(struct foo) );
}
}
void foo_destroy( foo_t *t )
{
if ( *t!=0 ) {
free(*t);
*t = 0;
}
}
void foo_tile( foo_t t )
{
t->some_member++;
}
And now here is an example client that uses the module:
bar.c:
#include "foo.h"
int main( int argc , char **argv )
{
foo_t toe;
foo_create( &toe );
toe = 0; /* <-- How to make the compiler (gcc) refuse this? */
toe = 1; /* <--- the compiler rejects this YAY!! */
}
The opaque type is actually a pointer to a dynamically allocated structure;
If I assign the value 0 to it I incur a memory leak which could be avoided If the compiler denied the assignment of 0 to this opaque pointer.
Assigning non-null values to the pointer isn't accepted by the compiler, so I supose that with a little more effort the same could be achieved for zero value.
Is it possible to disable this assignment? How can I achieve that?
If using some bit of C++ or gcc specific constructs is needed, I'll be ok with that, although a pure C solution would be nice.
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,您的 typedef 是错误的:
typedef struct foo foo_t;
(因此它是您的main
,否则编译器将捕获对结构的赋值)。对于不透明类型,通常会执行以下操作:
typedef struct foo *foo_t;
。否则,您的toe
将不会是您发布的示例中的指针(这就是为什么您必须使用 & 传递它)。考虑到foo_create
中的malloc
,我很确定您输入了错误的 typedef。其次,问问自己,如何释放内存?通过使用清理函数(
foo_destroy
),对吧?用户应该将此指针传递给清理函数。所以考虑一下:如果用户无知到给它分配一个整数,为什么她不会无知到忘记清理?
编辑
Stéphane Gimenez 评论 typedef struct foo foo_t 是OP想要的。我想强调这一点:
First of all, your typedef is wrong:
typedef struct foo foo_t;
(and so it yourmain
, otherwise the compiler will catch the assignments to structures).For opaque types it is customary to do something like:
typedef struct foo *foo_t;
. Otherwise yourtoe
wouldn't be a pointer in the example you posted (that's why you had to pass it with &). Considering themalloc
infoo_create
, I am pretty sure you typed the wrong typedef.Second, ask yourself, how are you going to free memory ? By using a cleanup function (
foo_destroy
), right ? And the user is supposed to pass this pointer to the cleanup function.So consider this: if the user is clueless enough to assign an integer to it, why wouldn't she be clueless enough to forget to cleanup ?
EDIT
Stéphane Gimenez commented typedef struct foo foo_t is what the OP want. I would like to underline that:
我不确定你能这样做。编译器将在 main() 中失败:
它也会在 foo_destroy() 中失败:
您可以尝试直接从 foo_create() 返回分配的内存,而不是传入 foo_t 参数(模拟构造函数):
I'm not sure you can do it that way. The compiler would fail in main():
It would also fail in foo_destroy():
You might try returning the allocated memory from foo_create() directly rather than passing in the foo_t parameter (emulating a constructor):
你的想法是错误的。您将如何启动本地 foo_t 变量?如果你输入
,那么 var 将包含垃圾。使其干净的唯一方法是输入
或
0
(如果您愿意),但这应该会发出警告。因此,您问题中的代码并不安全,它可能会崩溃。您可以做的就是向 foo_tile 添加 nonnull 属性,即:
这将阻止 foo_tile(NULL); ,并且在某些编译器中,即使
它可能只是使其成为警告,而不是硬错误。
You're thinking about this wrongly. How would you initiate a local foo_t variable? If you type
then var will contain garbage. The only way to make it clean is to type
or
0
if you wish, but that should emit a warning. The code in your question is thereby not safe, it might crash.What you can do is to add the nonnull attribute to foo_tile, i.e.:
That will prevent
foo_tile(NULL);
and in some compilers eventhough it'll likely just make it a warning, not a hard error.