我正在做一个高度多线程的项目,我想知道是否有一种方法可以让编译器标记对C库(例如strtok_r的strtok intsead )的不可重入调用?如果没有,是否有不可重入的调用列表,以便我可以定期grep我的代码库?
一个相关的问题是,是否有一种方法可以标记不可重入调用的3d party库使用。
我假设可重入性意味着线程安全,但不一定相反。在线程化项目中使用不可重入调用有充分的理由吗?
发布于 2011-06-24 09:34:51
对于source,您可能会坚持要求每个源文件都包含一行:
#include <beware.h>在C标头之后,然后beware.h标头文件包含:
#define strtok unsafe_function_call_detected_strtok
#define getenv unsafe_function_call_detected_getenv或者不太可能是真实函数的一些其他合适的名称集。这将导致编译和/或链接器错误。
对于库来说,这有点困难。您可以考虑使用nm来提取每个对象文件中所有未解析的名称,并确保不会调用任何不安全的名称。
这不是由编译器来做的,但是将它合并到构建脚本中将是非常容易的。请参阅以下文字记录:
$ cat qq.c
#include <stdio.h>
int main (int argc, char *argv[]) {
printf ("Hello, world.\n");
return 0;
}
$ gcc -c -o qq.o qq.c
$ nm qq.o
00000000 b .bss
00000000 d .data
00000000 r .rdata
00000000 t .text
U ___main
00000000 T _main
U _puts您可以使用U标记在该输出中看到未解析的符号( gcc非常巧妙地决定使用puts而不是printf,因为我为它提供了一个不带格式化命令的常量字符串)。
发布于 2011-06-26 23:41:20
是否有不可重入的调用列表,以便我可以定期grep我的代码库?
我查看了GNU libc函数列表,找出了使用_r的函数列表,如下所示。
asctime,crypt,ctime,drand48,ecvt,encrypt,erand48,fcvt,fgetgrent,fgetpwent,getdate,getgrent,getgrgid,getgrnam,gethostbyaddr,gethostbyname2,gethostbyaddr,gethostbyname2,gethostbyname,getmntent,getnetgrent,getpwent,getpwnam,getpwuid,getutent,getutid,getutline,gmtime,hcreate,hdestroy,hsearch,initstate,jrand48,lcong48,lgamma,lgammaf,lgammal,localtime,lrand48,mrand48,nrand48,ptsname,qecvt,qfcvt,rand,readdir64,readdir,seed48,setkey,setstate,srand48,s随机,strerror,strtok,tmpnam,ttyname
发布于 2011-06-24 09:37:45
回答你问题的第二部分:
非重入调用可以以一种给它们提供性能优势的方式来实现。在这种情况下,如果您知道您只从一个线程(或在一个临界区内)进行这些调用,并且它们是您的瓶颈,那么选择不可重入的调用是有意义的。但只有在有性能测量表明这样做是至关重要的情况下,我才会这样做……并仔细记录下来..
https://stackoverflow.com/questions/6462382
复制相似问题