Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't initialize static structure with function pointer from another translation unit?

Tags:

c

c99

c89

The Python documentation claims that the following does not work on "some platforms or compilers":

int foo(int);  // Defined in another translation unit.
struct X { int (*fptr)(int); } x = {&foo};

Specifically, the Python docs say:

We’d like to just assign this to the tp_new slot, but we can’t, for portability sake, On some platforms or compilers, we can’t statically initialize a structure member with a function defined in another C module, so, instead, we’ll assign the tp_new slot in the module initialization function just before calling PyType_Ready(). --http://docs.python.org/extending/newtypes.html

Is the above standard C89 and/or C99? What compilers specifically cannot handle the above?

like image 714
Josh Haberman Avatar asked Aug 08 '11 21:08

Josh Haberman


2 Answers

That kind of initialization has been permitted since at least C90.

From C90 6.5.7 "Initialization"

All the expressions in an initializer for an object that has static storage duration or in an initializer list for an object that has aggregate or union type shall be constant expressions.

And 6.4 "Constant expressions":

An address constant is a pointer to an lvalue designating an object of static storage duration, or to a function designator; it shall be created explicitly, using the unary & operator...

But it's certainly possible that some implementations might have trouble with the construct - I'd guess that wouldn't be true for modern implementations.

like image 142
Michael Burr Avatar answered Nov 05 '22 22:11

Michael Burr


According to n1570 6.6 paragraph 9, the address of a function is an address constant, according to 6.7.9 this means that it can be used to initialize global variables. I am almost certain this is also valid C89.

However,

On sane platforms, the value of a function pointer (or any pointer, other than NULL) is only known at runtime. This means that the initialization of your structure can't take place until runtime. This doesn't always apply to executables but it almost always applies to shared objects such as Python extensions. I recommend reading Ulrich Drepper's essay on the subject (link).

I am not aware of which platforms this is broken on, but if the Python developers mention it, it's almost certainly because one of them got bitten by it. If you're really curious, try looking at an old Python extension and seeing if there's an appropriate message in the commit logs.

Edit: It looks like most Python modules just do the normal thing and initialize type structures statically, e.g., static type obj = { function_ptr ... };. For example, look at the mmap module, which is loaded dynamically.

like image 2
Dietrich Epp Avatar answered Nov 05 '22 22:11

Dietrich Epp