こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

アドレスの比較について

こんにちは。質問させてもらいます。

pcap.hを使って、取得したパケットの送信元アドレスと送信先アドレスを比較させて、違うアドか同じアドかを判断したいと考えています。
しかし、送信元アドレスと送信先アドレスが明らかに違うのに、同一だと判断してしまいます。原因を教えてもらえないでしょうか。


ipアドレスを格納する構造体は

struct ip
{
struct in_addr ip_src, ip_dst;
};

としました。

↓が試した方法です。

1.inet_ntoaの値をそのまま比較

if ( inet_ntoa(ip->ip_src) == inet_ntoa(ip->ip_dst) )
{
printf("\nアドレスいっしょ\n");
//↓はアドレスが違っているかどうか確認
printf("src:%s\n",inet_ntoa(ip->ip_src));
printf("dst:%s\n",inet_ntoa(ip->ip_dst));
}
else
{
printf("\nアドレス違う\n");
}



2.strcmpを使う
if ( strcmp(inet_ntoa(ip->ip_src),inet_ntoa(ip->ip_dst)) == 0)
{
printf("\nアドレスいっしょ\n");
printf("src:%s\n",inet_ntoa(ip->ip_src));
printf("dst:%s\n",inet_ntoa(ip->ip_dst));
}
else
{
printf("\nアドレス違う\n");
}


どちらでやってもアドレスは同じと判断してしまいます。printfで確認するときっちり違うアドが表示されるのに・・何故?
きちんとアドレスを比較してくれるようにif文の中身を変えたいです。
ご助力お願いできますか。

投稿日時 - 2008-12-21 00:56:19

QNo.4571564

困ってます

質問者が選んだベストアンサー

★アドアイス
>inet_ntoa の戻り値を free しないのにメモリリークしないことを不思議に…
 ↑
 不思議じゃないです。
 C言語の標準関数でも内部に static なバッファを使って
 戻り値を返す関数が沢山あります。
 (strtok、gmtimeなどなど)

正しいサンプル:
char srcBuff[ 32 ];
char dstBuff[ 32 ];

strcpy( srcBuff, inet_ntoa(ip->ip_src) );
strcpy( dstBuff, inet_ntoa(ip->ip_dst) );

if ( !strcmp(srcBuff,dstBuff) ){
 printf("\nアドレスいっしょ\n");
 //↓はアドレスが違っているかどうか確認
 printf("src:%s\n", srcBuff );
 printf("dst:%s\n", dstBuff );
}
else{
 printf("\nアドレス違う\n");
}

注意事項:
マルチスレッド内で inet_ntoa のような関数を
複数のスレッドから呼び出すときには排他処理を行って下さい。
排他処理をしないと正しく変換(取得)出来ません。


今回の質問は良くある間違いです。
今後、staticな戻り値に注意しましょう。

http://www.geekpage.jp/programming/winsock/tips-inet_ntoa.php
http://www.geekpage.jp/programming/winsock/tips-gethostbyname.php

投稿日時 - 2008-12-21 02:21:30

お礼

ご回答有難う御座います。
分かりやすいサンプルを添えて頂いた事感謝します。
末尾のサイトも有難く参考にさせて頂きます。

投稿日時 - 2008-12-21 05:04:49

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

>>inet_ntoa の戻り値を free しないのにメモリリークしないことを不思議に…
> 不思議じゃないです。

ちょっと話が難しすぎたかな・・・。

今回の質問者は、関数を呼び出したら毎回違うアドレスが返ってくる、と思ってプログラムを組んでいたわけですよね。それなら、free する責任は普通に考えて呼び出し側にあることになります。ところが自分では free してないのですから、メモリリークの可能性があることにすぐに気がつかなければなりません。

逆に、ちゃんとわかっている人なら「戻り値を返す関数が沢山あります」と言えるでしょう。こういう人は、ご指摘のように「排他処理をしないと正しく変換(取得)出来ません」というところまで、先回りして考えることができるわけです。あるべき姿ですね。

こういうベテランの人が「不思議じゃない」と思うことと、質問者が自身のプログラムを疑問に思わないことはまったくレベルが違う話です。

呼び出された関数がその内部で領域確保してくれてそのポインタを返す仕様は誤りではありませんが、呼び出した側がなにも考えずにそのポインタを捨てるのは誤り(要するに「よろしくない」)です。今回、質問者は前者の仕様だと考えて関数を呼び出し、後者のようにプログラムを組んでいるわけで、一貫性がありません。指摘されないとこの祖語に気がつかないようでは先が思いやられる、という意味です。

「サンプルなので free は省略しました」ということなら、仕様を誤って理解していますし、「free は忘れていました」ということなら、「誰が free するのか常に考えてプログラムしましょう」ということになります。どちらにしても、問題ですよね。

投稿日時 - 2008-12-21 02:56:24

お礼

ご回答有難う御座います。
ご忠告は真摯に受け止めさせて頂きます。

投稿日時 - 2008-12-21 04:59:04

ANo.2

すでに正しい回答が出ているようですね。

inet_ntoa の戻り値が char * になっていて、呼び出し側からはリターン用のアドレスを引き渡していないことに気がつけば、こういう間違いはしないはずです。

というか、inet_ntoa の戻り値を free しないのにメモリリークしないことを不思議に思わないようでは、この先、「気分しだいで動いたり動かなかったり」のプログラムを量産することになるでしょう。この種のバグはデバッガでもなかなかとれないですよ。

これは指摘しなくても気が付いていると信じたいですが
> アドレスは同じと判断してしまいます
アドレスを比較しても文字列が等しいかどうかは判定できないと思います。

さらに余談ですが
> if ( strcmp(inet_ntoa(ip->ip_src),inet_ntoa(ip->ip_dst)) == 0)
今回はあまり関係ありませんが、この書き方だとコンパイラが変わると動作が変わるかもしれませんね。

投稿日時 - 2008-12-21 01:48:32

ANo.1

inet_ntoa関数は内部的に持っているchar型配列の先頭ポインタを返すような
仕様になっているのではないでしょうか?
(inet_ntoaの戻り値をfreeするような記述があれば違いますが。)

となると当然どんな引数を与えても同じ値が返ってきてしまいます。
また、strcmpを使う場合必ず同じになってしまうでしょう。

よって、戻り値の値をそのまま比較せず、一度char型配列に格納してから
strcmpで比較するようにすれば良いでしょう。

投稿日時 - 2008-12-21 01:10:30

お礼

ご回答有難うございます。参考になりました。

投稿日時 - 2008-12-21 04:55:20

あなたにオススメの質問