1

我正在为现有的大型软件工具添加一项功能(该工具用于 dns 数据包捕获和解析等)。我注意到原始代码中有一些奇怪的地方,无法弄清楚解释是什么。该代码有一个用于存储 IP 地址(IPv6 和 IPv4)的结构,如下所示:

typedef struct {
    int         af;  
    union {
        struct in_addr      a4;  
        struct in6_addr     a6;  
    } u; 
} iaddr; 

此外,它具有将这样存储的地址转换为字符串的功能:

static const char * ia_str(iaddr ia) {                                  
    static char ret[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
    (void) inet_ntop(ia.af, &ia.u, ret, sizeof ret);
    return (ret);
}

现在,在打印数据包时,代码会执行以下操作来打印源地址和目标地址以及端口:

void output(const char *descr, iaddr from, iaddr to, ...
    ...
    fprintf(stderr, "%s:%u ", ia_str(from), sport);
    fprintf(stderr, "-> %s:%u", ia_str(to), dport);

到目前为止,一切都很好(我认为)。这是已发布的代码,似乎工作正常。现在,当我进行这个微小的改变时,只需将上面的两个 fprintf 行合并为一个(如果我尝试使用 sprintf 而不是 fprintf 也会发生这种情况):

    fprintf(stderr, "%s:%u -> %s:%u", ia_str(from), sport, ia_str(to), dport);

该程序在两个位置打印相同的地址(即 ia_str(from) 地址)!

我难住了。请帮忙。提前致谢!

4

2 回答 2

3

这很可能是因为 ia_str() 正在返回一个指向静态缓冲区的指针。

因此,发生的情况是对 ia_str() 的调用都是在设置对 fprintf() 的调用之前计算的。ia_str() 的返回值被压入堆栈,但因为它是一个静态缓冲区,所以它包含最后放入其中的值。恰好来自 is_str(from)。

于 2013-02-06T04:11:46.737 回答
2

向 fprintf 传递相同的地址,因为从 ia_str 的返回将在任意数量的调用中返回相同的地址,只有最后一次调用的更改才会有效。所以在调用 fprintf 时,最后调用的函数 ia_str(from) [函数将从右到左调用] 会修改 ret,只有那个才会出现。它会是这样的:

fprintf(stderr, "%s:%u -> %s:%u", 0x12345, sport, 0x12345, dport);

相同的地址,相同的价值。

于 2013-02-06T04:12:13.763 回答