64bitプロセスの4バイト境界でselect()が使えない – プログラミング – Home

64bitプロセスの4バイト境界でse...
 
通知
すべてクリア

[解決済] 64bitプロセスの4バイト境界でselect()が使えない


たま
 たま
(@たま)
ゲスト
結合: 23年前
投稿: 50
Topic starter  

よろしくお願いします。

環境は、
Windows 7 Pro 64bit
Visual Studio 2010 Pro (VC++)
を使用しております。

64ビット用のプロセスでSocket通信を作成しておりますが、
構造体メンバーのアライメントを4バイトで作成すると、
select()で失敗するようになってしまいます。
※もしかしたら、select()失敗の原因は、FD_ZEROもしくはFD_SET?(憶測)

「構造体メンバーのアライメントを4バイトにしたまま」で、
selectを使用する方法。または、select()の代わりとなる関数を使用する方法。
をご存知の方がいましたら教えていただけないでしょうか?

下記に簡単なコードを記述させて頂きます。
------------------------------------------------------------------
#include <winsock2.h>

unsigned short port_no = 8050; // ポート番号
int rc; // リターンコード
WSADATA wWsaData; // WinSock情報
SOCKET m_MySocket; // ソケット
SOCKADDR_IN m_SockAddr; // ソケット情報
int SockAddrSize; // ソケットサイズ
fd_set fd;
timeval timeout;
int rtc;

// WinSockの初期化
if( WSAStartup( MAKEWORD(2,0), &wWsaData ) != 0 ){
rc = -1;
}

// ソケット生成
if( (m_MySocket = socket( PF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET ){
rc = -2;
}

// Bind
m_SockAddr.sin_family = PF_INET;
m_SockAddr.sin_port = htons(port_no);
m_SockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
memset( m_SockAddr.sin_zero, 0x00, sizeof(m_SockAddr.sin_zero) );

if( bind( m_MySocket, (struct sockaddr *)&m_SockAddr, sizeof(m_SockAddr) ) != 0 ){
rc = -3;
}

// Listen
if( listen( m_MySocket, 5 ) != 0 ){
rc = -4;
}

// タイムアウト設定
FD_ZERO( &fd );
FD_SET( m_MySocket, &fd );
timeout.tv_sec = 0;
timeout.tv_usec = 500;

// ここのselect()が-1を返します
rtc = select( 1, &fd, NULL, NULL, &timeout );

// エラーコードは10038が返ってきます
// エラーコードの内容
// ソケット以外に対して操作が試行されました。
// ソケット ハンドル パラメータの参照先のソケットが有効ではないか、
// fd_set のメンバが有効ではありません。
rtc = WSAGetLastError();
-------------------------------------------------------------------


引用未解決
トピックタグ
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

>rtc = select( 1, &fd, NULL, NULL, &timeout );
rtc = select( m_MySocket + 1, &fd, NULL, NULL, &timeout );
ではないのですか。そ~いう簡単な問題じゃないか(vv;)。


返信引用
たま
 たま
(@たま)
ゲスト
結合: 23年前
投稿: 50
Topic starter  

仲澤@失業者さん

御指摘ありがとうございます。
第1引数は無視される仕様だったと思いますが、
お教え頂いた内容で修正して動作させてみました。
結果は、やはりselect()で-1を返してしまいます。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

そうなると本格的に
#pragma pack( push, 4)
  ~ 
#pragma pack( pop)
の問題となり、WinSockを含めて、外部ライブラリの定義に対して
上のパックを「かけている」可能性があります。
当然ですが、それはあってはならないことです。
この認識は大丈夫ですか?。


返信引用
たま
 たま
(@たま)
ゲスト
結合: 23年前
投稿: 50
Topic starter  

仲澤@失業者さん

御指摘ありがとうございます。
>#pragma pack( push, 4)
>  ~ 
>#pragma pack( pop)
>の問題となり、WinSockを含めて、外部ライブラリの定義に対して
>上のパックを「かけている」可能性があります。
>当然ですが、それはあってはならないことです。
>この認識は大丈夫ですか?。
構造体メンバーのアライメントに関しては、
ソースコードに#pragma packを使用しておらず、
VisualStudio2010開発環境(プロジェクト)設定の、
コンパイラオプション(/Zp)で設定しております。
【参考URL】
http://msdn.microsoft.com/ja-jp/library/xh3e3fd0.aspx


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

>コンパイラオプション(/Zp)で設定しております。

その方法では、自前のソース以外の、DLL、ライブラリを使用する
ことはできません。それらの外部のバイナリ内の各オブジェクトの
オフセット位置は、それらがコンパイルされたときに決定されています。
つまり出荷時に固定されているわけです。
Zpを指定したからと言って、それらのあらためてコンパイルされない
DLLやLibのアライメントが調整されるわけではありません。

Zpが安全に使える場合とは「一切の外部ライブラリとソースを使用しないで、
自前のコードのみをコンパイルするプロジェクト」だけです。

まず、Zpを外し、自分のコードの必要な部分だけに#pragma(・・・)
しましょう。
この方法が、Windowsアプリを作成する場合の唯一のパック方法
となります。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

気になっているところが、
 64BIT版って、ヘッダーファイルのディレクトリーが別になっている場合って
ありませんでしたっけ?
「winsock2.h」なんてありそうですよね?


返信引用
たま
 たま
(@たま)
ゲスト
結合: 23年前
投稿: 50
Topic starter  

仲澤@失業者さん

御教授ありがとうございます。

>Zpが安全に使える場合とは「一切の外部ライブラリとソースを使用しないで、
>自前のコードのみをコンパイルするプロジェクト」だけです。
Zpの使用はかなり制限される事になるのですね。

>まず、Zpを外し、自分のコードの必要な部分だけに#pragma(・・・)
>しましょう。
>この方法が、Windowsアプリを作成する場合の唯一のパック方法
>となります。
承知いたしました。
上記方法(#pragma)で対処していく事にしようと思います。

詳しく丁寧にお答え頂き、ありがとうございました。

ITOさん

御教授ありがとうございます。

>気になっているところが、
>64BIT版って、ヘッダーファイルのディレクトリーが別になっている場合って
>ありませんでしたっけ?
>「winsock2.h」なんてありそうですよね?
ヘッダーファイルによっては別になっている事があるのでしょうか。
「winsock2.h」が入っているディレクトリーは一箇所しか見つける事ができませんでした。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

ヘッダーは#ifdefで切り分けのようです(_WIN64とか)。
Libは当然分かれてますけど。

Winsock2.hは、当たり前ですが独自に#pragma pack()はしません。
アライメントはデフォルトの8Byte(だったかな)に固定のはず。

そもそも何のために4Byteにしたいのかが不明ですが。
一般にそれが必要になるのは、ストリーム(ファイル、通信)などの
データが、そうなっている場合などに限られるはずで、その場合でも
通信や保管読み込み対象のstructをパックするのが普通です。
つまり、一般に、Zpを使う機会はまったくないと断言できます。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました