Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用此netbsd代码是否可重入_C_Multithreading_Static_Reentrancy_Netbsd - Fatal编程技术网

C 使用此netbsd代码是否可重入

C 使用此netbsd代码是否可重入,c,multithreading,static,reentrancy,netbsd,C,Multithreading,Static,Reentrancy,Netbsd,我正在通过阅读NetBSD源代码来学习“阅读代码”。 (对于任何感兴趣的人来说,这是我正在阅读的) 我发现这个函数: /* convert IP address to a string, but not into a single buffer */ char * naddr_ntoa(naddr a) { #define NUM_BUFS 4 static int bufno; static struct { char str[16]; /* xxx.xxx.xxx

我正在通过阅读NetBSD源代码来学习“阅读代码”。
(对于任何感兴趣的人来说,这是我正在阅读的<代码阅读:开源透视图>)

我发现这个函数:

/* convert IP address to a string, but not into a single buffer
*/
char *
naddr_ntoa(naddr a)
{
#define NUM_BUFS 4
    static int bufno;
    static struct {
    char str[16];   /* xxx.xxx.xxx.xxx\0 */
    } bufs[NUM_BUFS];
    char *s;
    struct in_addr addr;

    addr.s_addr = a;
    strlcpy(bufs[bufno].str, inet_ntoa(addr), sizeof(bufs[bufno].str));
    s = bufs[bufno].str;
    bufno = (bufno+1) % NUM_BUFS;
    return s;
#undef NUM_BUFS
}
它引入了4种不同的临时缓冲区来包装inet_ntoa函数,因为inet_ntoa不是可重入的。
但在我看来,naddr_ntoa函数也不是可重入函数:
静态bufno变量可由其他变量操作,因此临时缓冲区似乎无法按预期工作


那么这是一个潜在的bug吗?

是的,这是一个潜在的bug。如果您想要一个类似的函数,很可能是可重入的,您可以使用它,例如(顺便说一下,它也可以处理IPv6)。

该代码来自
src/sbin/routed/trace.c
,它不是一个通用的库例程,只是一个仅在路由程序中使用的自定义hack。同一文件中的
addrname()
函数出于相同的原因使用了相同的技巧。它本身甚至不是NetBSD代码,而是最初来自SGI,由Vernon Schryver维护(请参阅)

允许在同一个表达式中使用多个调用只是一种快速的技巧,例如在一个printf()调用中使用结果:例如:

printf("addr1->%s, addr2->%s, addr3->%s, addr4->%s\n",
       naddr_ntoa(addr1), naddr_ntoa(addr2), naddr_ntoa(addr3), naddr_ntoa(addr4));
路由源文件(if.c、input.c、rdisc.c)中有几个类似的用法示例

这段代码中没有bug。路由程序不是多线程的。在这次黑客攻击中,可重入性根本没有得到解决。这个技巧是为一个与重入无关的特定目的而设计的。代码读取作者将此技巧与重入关联是错误的

这只是一种隐藏在静态变量数组中保存多个结果的方法,而不是在单个表达式需要多个结果时,将这些结果从一个静态变量单独复制到调用函数中的单独存储中


请记住,除了标识符的有限范围外,静态变量具有全局变量的所有属性。当然,在函数中不受保护地使用全局(或静态)变量会使该函数不可重入,但这不是全局变量引起的唯一问题。在routed中使用完全可重入函数是不合适的,因为它实际上会使代码变得比必要的更复杂,而这种黑客行为使调用代码保持干净和简单。不过,最好对黑客行为进行适当的记录,以便未来的维护人员更容易发现何时需要调整
NUM_BUFS

事实上,在我看来,他们这样写似乎是为了避免
malloc
,而不是为了重新进入
inet_ntoa
,根据我读到的至少一个手册页,它只使用一个静态缓冲区(这可能被NetBSD开发人员认为是不可接受的)。你能为它的可重入性添加一个引用吗?@nnoneo好吧,如果在某个地方隐藏了一个全局/静态缓冲区,那么你可以提供自己的缓冲区,因为它是可重入的(当然,除非它是以不可重入的方式调用的)。在这里扮演魔鬼代言人,但它可以有其他内部状态使其不可重入。(我认为不是这样。)
printf
不是可重入的,但您的逻辑会表明它是可重入的。如果
inet\u ntop
调用
sprintf
(这不能保证是可重入的)?@nneonneo你是对的。我看的每一个地方,每个人都说它是可重入的,但阅读手册页面(包括我答案中链接的POSIX页面)却没有提到可重入或线程安全。我将重新表述我的答案。:)