初めて質問させて頂きます。
現在、LinuxのUnixドメインを使用した内部通信プログラムを
作成しているのですが、recvfrom関数の戻り値で-512という値が
返ってきて頭を悩ませています。
いろいろなHP等でrecvfrom関数の戻り値について記述されている内容は
受信サイズか-1となっているのですが・・・-512という値については
さっぱりでした。
-1の場合は、errnoが入るようなのですが、-512の場合、errnoが0のままで何もはいっていないように見えます。
どの様な問題が発生しているかの見当もつかない状態です。
すみませんが、宜しくお願い致します。
A 回答 (8件)
- 最新から表示
- 回答順に表示
No.8
- 回答日時:
ANo6です。
Ano.7に同意見です。
Ano.1の補足に掲載された部分のプログラムには特に問題なく他の部分に問題があってデータの累積受信量が増えるにつれ、なにかおかしなことが起きているように思えます。
ためしに、rcvfromでデータを受信して何もせずに捨てるだけのプログラムを書いて(現在のプログラムから該当部分以外を削って作って)、テストしてみたらどうでしょうか。
それでも症状が変わらないようなら、ライブラリやカーネルのバグ/メモリリークかもしれません。
No.7
- 回答日時:
再度 ANo.5 です。
「早速内容ですが、sizeof(svr_addr.sun_family)を対象にしたのは、
linux/un.hにてstruct sockaddr_unの定義が
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
};
となっていたためです。」
ですが、これは今回は(多分)正しいですが、一般的には正しくない可能性もあるので注意してください。私の理解では、構造体のメンバー変数鵜の順序はプログラムで書いた通りですが、メンバー変数の間が必ず「詰まった」状態となるかどうかは、つまり「空き」が生じる可能性があるかもしれない、処理系や機種依存だと思います。ということで、SUN_LENを使うのが一番正しいですね。
で、本題ですが、私の直感では、どこか他の部分で悪さしているように思いますので、これ以上、新たな情報がない限り、進展はみられないでしょう。
No.6
- 回答日時:
症状からすると、どこかにバグがあってスタックを破壊しているっぽいのですが。
あるいはglibcを入れ替えたとかの副作用?(考えにくいですが)「何百回と正常に動作していたものが急にメモリ破壊を
起こすことはあるのでしょうか?」
というところをもうちょっと説明して貰えませんか。
プログラムをまったく変更しないのにある日急に変になったのでしょうか?再コンパイルはしていませんか?カーネルやライブラリの入れ替えはしていませんか?
少なくとも、デバッグのためのprintf文を入れるというだけの変更でも、メモリ破壊系の症状は変わったりしますので油断ならないです。
なお、
islen = sizeof(rcv_addr.sun_path);
は
islen = sizeof(rcv_addr);
ではないですか?今回の場合これで害はないと思いますが。
あと、int main(・・なんですからreturn;ではなくて return 1;(エラー終了の場合)としたほうが気持ちいいですね。
この回答への補足
ご回答ありがとうございます。
再コンパイル等についてですが、本問題発生後にデバッグ情報出力
強化等の改造は実施いたしましたが、問題発生時の再コンパイル等
はありません。また、その改造後も現象が発生しております。
カーネル・ライブラリの変更はありません。
「何百回と正常に動作していたものが・・・」というあたりが
紛らわしい表現だったかと思いますが、動作確認のために問題箇所に
対して大量にイベントを送信し続けるといった試験をいたしました。
その結果最初は正常に受信できるのですが、数時間後に本問題が
発生して受信エラーになってしまいます。
問題が発生するまでの時間はまちまちで、11時間かかることもあれば
1時間程度で発生することもあります。
returnに関しましては・・・重ね重ねすみません。
No.5
- 回答日時:
「メモリの破壊ですか、その可能性はありそうですね。
ただ、理解が不足しているだけなのかも知れませんが、
何百回と正常に動作していたものが急にメモリ破壊を
起こすことはあるのでしょうか?」
ということは問題が起きているのはこのプログラムではないということなのかな?
いずれにせよ、私が書いた(でも忘れてしまっていた)動いている(ハズ)のコードでは、長さの計算を、
#ifdef SUN_LEN /* derived from 4.4BSD */
*size = SUN_LEN(sock_addr);
#else
*size = sizeof(struct sockaddr_un)
- sizeof(sock_addr->sun_path) + strlen(sock_addr->sun_path);
#endif
としていますね。また CentOS での SUN_LEN の定義は
# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen ((ptr)->sun_path))
となっていて(ちょっとトリッキーですが)上の私の定義と基本的に同じです。
ilen = strlen(svr_addr.sun_path) + sizeof(svr_addr.sun_family);
ですが、sizeof(svr_addr.sun_family) はやっぱりおかしくないですか?svr_addr.sun_family は sum_family_t になっていて、この定義は
linux/socket.h:typedef unsigned short sa_family_t;
ですから。
この回答への補足
ご回答ありがとうございます。
まず、返信が遅れまして申し訳ありません。
早速内容ですが、sizeof(svr_addr.sun_family)を対象にしたのは、
linux/un.hにてstruct sockaddr_unの定義が
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
};
となっていたためです。
また、ご指摘のとおりbind時のサイズ指定にてSUN_LENを使用して
みたのですが、問題の現象が再現してしまいました。
No.4
- 回答日時:
ちょっとお酒も入って検証するのが面倒なのですが、
ilen = strlen(svr_addr.sun_path) + sizeof(svr_addr.sun_family);
ですが、こんなことしたっけかなぁ(でも自信なし)。
ひょっとしてメモリ壊してませんか?-512 ですから最初の2バイトがクリアされてる?
buf とか sockaddr とかを main の外に出してみるとどうなりますか?あるいは ret の前に適当な配列を入れてみるとか、変数の順序を変えてみるとか。
余談ですが、最後の return に値がないのは気持ち悪いです。
この回答への補足
ilenの計算ですが、bind関数の第4引数は、第3引数のサイズと
あった為、上記処理でサイズを求めて設定してます。
メモリの破壊ですか、その可能性はありそうですね。
ただ、理解が不足しているだけなのかも知れませんが、
何百回と正常に動作していたものが急にメモリ破壊を
起こすことはあるのでしょうか?
最後にreturnに値がないことについて・・・
元々void main()って形が好きだったんですが、コンパイル時にvoidだと警告が出てしまうのでintに強制したんですが・・・
癖が抜けなくて^^;
No.3
- 回答日時:
こちらの環境でそのソースをコンパイル&リンクして実行しました。
正常に動作しています。(INTEL-solari10 sun-studio-11 でコンパイル)
linux(CENTOS4.4) のgcc(3.4.6)では、コンパイルエラーのため確認出来ませんでした。
No.2
- 回答日時:
どのような確認のしかたで戻り値が-512であると、判断したのでしょうか。
ssize_t ret;
ret=recvfrom(...);
printf("ret=%d\n",ret);
上記のように確認していますか。正しく戻り値を判定していないように思われます。
ssize_tは訳の分からないサイズですが、sizeof(ssize_t)が4ですので、int型と考えて良いでしょう。
この回答への補足
下の回答でも記述したのですが、intデータに戻り値を格納し、
%dで表示しております。
但し、戻り値の格納先についてはintデータを使用しており、
ssize_tを使っていないのですが、戻り値の格納サイズに関しては
共に4バイトデータの為、問題ない気がしております。
No.1
- 回答日時:
カーネルが壊れているか、あなたのプログラムが間違っているかです。
当然後者でしょうけど。
そもそもなぜ-512という戻り値であると判断したのでしょうか?
プログラムの当該部分を示してください。
recvfromの返り値を shortの変数で受けたりしてないですよね。
この回答への補足
戻り値を%dで表示した時、-512と表示されました。
又、戻り値の格納先はintの変数にしております。
unsigned intではないので-512と表示されました。
又、長くなってしまうのですが、該当処理は以下の通りです。
#define SNDSOCKPATH "./sock_file"
int main(int argc, char *argv[])
{
struct sockaddr_un svr_addr;
struct sockaddr_un rcv_addr;
int socka = 0;
int ilen = 0;
int c = 0;
int islen = 0;
int ret = 0;
int en;
char buf[4096];
char pbuf[256];
socka = socket(AF_UNIX, SOCK_DGRAM, 0);
if(0 > socka)
{
printf("a socket err %d\n", errno);
return;
}
unlink(SNDSOCKPATH);
memset(&svr_addr, 0, sizeof(svr_addr));
svr_addr.sun_family = AF_UNIX;
strcpy(svr_addr.sun_path, SNDSOCKPATH);
ilen = strlen(svr_addr.sun_path) + sizeof(svr_addr.sun_family);
if(bind(socka,(struct sockaddr *)&svr_addr, ilen) < 0)
{
close(socka);
unlink(SNDSOCKPATH);
return;
}
while(1)
{
en = 0;
errno = 0;
memset(&rcv_addr, 0, sizeof(rcv_addr));
memset(pbuf, 0, sizeof(pbuf));
islen = sizeof(rcv_addr.sun_path);
ret = recvfrom(socka, (char *)&buf, sizeof(buf), 0,
(struct sockaddr*)&rcv_addr, &islen);
en = errno;
perror(pbuf);
printf("recvfrom ret[%d] errno [%d(0x%08x)] "\
"sun_path[%s] sun_family[%d]\n",
ret, en, en, rcv_addr.sun_path,
rcv_addr.sun_family);
}
return;
}
-512を判断したのは、戻り値retを参照した為です。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- JavaScript カラーミーショップのsectionループ内で、[引数][戻り値]ありの関数的な処理を行いたいです。 1 2022/05/07 19:39
- その他(プログラミング・Web制作) pythonのプログラムについての質問です。 1 2023/05/26 10:31
- Visual Basic(VBA) Excel のユーザー定義関数でソルバーが動作しない 1 2022/09/05 19:51
- 数学 条件付き極値問題といわれる問題です。ラグランジュの乗数法 について、質問したいことがあります。 条件 3 2023/05/15 21:38
- 医学 有機溶剤の影響で健康を失った肝臓は正常な状態に戻らないのでしょうか? 1 2023/07/16 07:55
- 数学 数学の問題です。 問1: ある(人数の非常に多い)集団から無作為に6名を選んで身長を測ったところ、そ 2 2022/12/09 12:03
- Java Java 南京錠 2 2023/02/04 11:46
- PHP php 入力画面から確認表示画面へ情報の受け渡しについて。 1 2023/06/07 18:00
- Java Java モンスターブリーダー 1 2023/02/05 09:44
- Excel(エクセル) Excelについて質問があります。 関数の数値入力についてなのですが、 b1にー c1に数値 がある 2 2023/05/28 12:30
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBAの配列サイズとメモリに関して
-
C言語で、メモリを解放しないで...
-
メモリアロケーション異常の発...
-
C#で別クラスインスタンスのメ...
-
大容量のメモリ確保をスワップ...
-
エクセル キャッシュメモリー...
-
メモリのセグメント違反の解決...
-
ちなみに、for (i = 0; str[i] ...
-
ReadEventLogについて
-
FindFirstFile ハンドル開放
-
大量件数のINSERT or UPDATE を...
-
動的メモリとexit(C言語)
-
パソコンを閉じる時いつも休止...
-
メモリの増加に関して
-
メモリの消費量について
-
スーパーマリオのパワーアップ...
-
CFileのOpenで例外(998:メモ...
-
「memcpy」と「strcpy」について
-
C言語:関数のメモリ上でのサイ...
-
アプリケーション上の文字を画...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語で、メモリを解放しないで...
-
VBAの配列サイズとメモリに関して
-
「ヒープサイズの設定」て何?
-
C言語における再帰呼び出しの...
-
エクセルVBA 大容量CSVファイル...
-
動的メモリとexit(C言語)
-
エクセルのメモリ使用状況/Appl...
-
メモリが不足しています(VBA)
-
ファイルマッピング関数で失敗
-
大容量のメモリ確保をスワップ...
-
メモリのセグメント違反の解決...
-
EXCEL-VBAにてADOのレコードセ...
-
メモリ不足
-
エクセル キャッシュメモリー...
-
【C言語】再帰が時間がかかる...
-
C#のOutOfMemoryException発生...
-
closeとメモリの開放について
-
バッチファイルでの実行EXEのメ...
-
メモリの解放について VB6 VBA
-
「memcpy」と「strcpy」について
おすすめ情報