当我将手册页读到dlopen()
时,我无意中发现了这段代码:
cosine = (double (*)(double)) dlsym(handle, "cos");
/* According to the ISO C standard, casting between function
pointers and 'void *', as done above, produces undefined results.
POSIX.1-2001 and POSIX.1-2008 accepted this state of affairs and
proposed the following workaround:
*(void **) (&cosine) = dlsym(handle, "cos");
This (clumsy) cast conforms with the ISO C standard and will
avoid any compiler warnings.
The 2013 Technical Corrigendum 1 to POSIX.1-2008 improved matters
by requiring that conforming implementations support casting
'void *' to a function pointer. Nevertheless, some compilers
(e.g., gcc with the '-pedantic' option) may complain about the
cast used in this program. */
我知道,将函数指针强制转换为空指针,反之亦然,这是未定义的行为.该标准之所以将其设置为未定义的行为,是因为体系 struct 的差异,其中函数指针可能与数据指针的大小不同,或者在某些情况下,函数指针实际上由两个值表示(至少我听说过).我理解解决办法如何避免未定义的行为,因为将cosine
的地址转换为void **
实际上只是将指向函数的指针的数据指针转换为void **
,这是完全有效的,当然,它也完全有效地取消对void **
的引用,并将dlsym()
返回的void *
赋给它.然而,如果存在前面提到的体系 struct 怪癖,这段代码难道不会像将函数转换为空指针一样容易出错吗?如果是这样的话,该标准不是也应该指定此解决方法也是未定义的行为吗?这进一步引出了这样一个问题:是否可以从一开始就实现dlsym()
功能的不容易出错的实现?