Making C module variables accessible as read-only

可紊 提交于 2019-12-01 00:37:53

问题


I would like to give a module variable a read-only access for client modules. Several solutions:

1. The most common one:

// module_a.c
static int a;

int get_a(void)
{
    return a;
}

// module_a.h
int get_a(void);

This makes one function per variable to share, one function call (I am thinking both execution time and readability), and one copy for every read. Assuming no optimizing linker.

2. Another solution:

// module_a.c
static int _a;
const int * const a = &_a;

// module_a.h
extern const int * const a;

// client_module.c
int read_variable = *a;
*a = 5;  // error: variable is read-only

I like that, besides the fact that the client needs to read the content of a pointer. Also, every read-only variable needs its extern const pointer to const.

3. A third solution, inspired by the second one, is to hide the variables behind a struct and an extern pointer to struct. The notation module_name->a is more readable in the client module, in my opinion.

4. I could create an inline definition for the get_a(void) function. It would still look like a function call in the client module, but the optimization should take place.

My questions:

  • Is there a best way to make variables modified in a module accessible as read-only in other modules? Best in what aspect?

  • Which solutions above would you accept or refuse to use, and why?

I am aware that this is microoptimization - I might not implement it - but I am still interested in the possibility, and above all in the knowing.


回答1:


Concerning option #4, I'm not sure you can make it inline if the variable isn't accessible outside the implementation file. I wouldn't count options #2 and #3 as truly read-only. The pointer can have the constness cast away and be modified (const is just a compiler "warning", nothing concrete). Only option #1 is read-only because it returns a copy.




回答2:


For speed identical to variable access, you can define an extern variable inside an inline function:

static inline int get_a(void)
{
    extern int a_var;
    return a_var;
}

This is simple and clear to read. The other options seem unnecessarily convoluted.

Edit: I'm assuming that you use prefixes for your names, since you write C. So it will actually be:

extern int my_project_a;

This prevents a client from accidentally making a variable with the same name. However, what if a client makes a variable with the same name on purpose? In this situation, you have already lost, because the client is either 1) actively trying to sabotage your library or 2) incompetent beyond reasonable accommodation. In situation #1, there is nothing you can do to stop the programmer. In situation #2, the program will be broken anyway.

Try running nm /lib/libc.so or equivalent on your system. You'll see that most libc implementations have several variables that are not defined in header files. On my system this includes things like __host_byaddr_cache. It's not the responsibility of the C library implementors to babysit me and prevent me from running:

extern void *__host_byaddr_cache;
__host_byaddr_cache = NULL;

If you start down the path of thinking that you have to force clients to treat your variable as read-only, you are heading down the path of fruitless paranoia. The static keyword is really just a convenience to keep objects out of the global namespace, it is not and never was a security measure to prevent external access.

The only way to enforce read-only variables is to manage the client code — either by sandboxing it in a VM or by algorithmically verifying that it can't modify your variable.




回答3:


  1. The most common one:

There's a reason why it's the most common one. It's the best one.

I don't regard the performance hit to be significant enough to be worth worrying about in most situations.



来源:https://stackoverflow.com/questions/6044141/making-c-module-variables-accessible-as-read-only

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!