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);

これまでのところ、とても良いです(私は思います)。これは公開されたコードであり、正常に機能しているようです。さて、この小さな小さな変更を行うと、上記の2つのfprintf行を1つに単純に結合します(これは、fprintfの代わりにsprintfを試した場合にも発生します)。

    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 からの return は何度呼び出しても同じアドレスを返すため、最後の呼び出しの変更のみが保持されます。そのため、fprintf を呼び出すと、最後に呼び出された関数 ia_str(from) [関数は右から左に呼び出されます] が ret を変更し、それのみが存在します。次のようになります。

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

同じアドレスなので同じ値です。

于 2013-02-06T04:12:13.763 に答える