何もしてないのにビルドエラー

[戻る]
シャノン 2004/07/26(月) 06:13:57
VC++ 7.1 です。

再現手順:
MFC AppWizard を起動します。
「高度な機能」タブで、「Windows ソケット」にチェックをつけます。
後は何も変更しないでプロジェクトを作成し、ビルドします。
すると、FreeAddrInfo / GetAddrInfo でビルドエラーが発生します。

皆さんの環境では発生しますか?
直し方の見当はつくんですが、そもそも、こんなところでエラーが出ていいものなの
か、と。
FAQ になってそうな気がしたんですが、簡単に調べた限りではみつかりませんでした。

#余談ですが、VS.NET 2003 のダイアログエディタで、書式→整列メニューを開くと…
#「左右中央」と「上下中央」の文字列、逆になってません?
#デバッグちゃんとしてんのかなぁ…

wood 2004/07/26(月) 07:10:04
やってみました WinXP Pro VS.NET2003
        Office 2003
        NORTON System Works 2004
        OASYS 2002
        AIR−H”
        「F]COBOL V6.1PRO

        DUAL OS Vine Linux 2.6r4

        SOTEC WinBook WL2130C 
        MEM 384MB
 
MFCアプリ SDI 「高度な機能」タブで、「Windows ソケット」にチェック
そのままビルドメニューからビルド
なんら「エラー」 らしいもの表示されませんでした

>#余談ですが、VS.NET 2003 のダイアログエディタで、書式→整列メニューを開く
と…
>#「左右中央」と「上下中央」の文字列、逆になってません?

提示された事柄についての事象確認できませんでした

環境壊れてませんか、再インストール(OSから)してみたらどうですか

シャノン 2004/07/26(月) 08:01:34
> WinXP Pro VS.NET2003
これはこちらも同じ環境です。
OS の違いにより発生する症状とは思えなかったため、OS は書きませんでしたが、
やはり、関係無さそうですね。
他にも詳細な環境など書いていただき恐縮ではありますが、関係ないと思われます。

> MFCアプリ SDI
デフォルトでは MDI になっていましたが、SDI で試してみました。
やはりエラーになります。

詳細を追記しておきます。
atlsocket.inl というファイルの、26 / 42 / 52 行目でエラーが発生します。
エラー内容は FreeAddrInfo / GetAddrInfo が見つからない、というようなものですが
ヘルプでこれらを見ると、関数名が小文字になっており、小文字に修正したところ
エラーが出なくなりました。
しかし、この修正が正しいとは思えません。

Platform SDK February 2003 をインストールしてあり、インクルードディレクトリは
VC++ 付属のものよりも、これらが優先されるようにしてあります。
(VC++ 付属の atlsocket.inl でも大文字になっていましたが)

> 提示された事柄についての事象確認できませんでした
> 環境壊れてませんか、再インストール(OSから)してみたらどうですか
この症状は会社の PC でも確認できました。
前者のビルドエラーについても、会社の PC でも確認してみたいと思います。

#OS の再インストールは… XP SP2 正式版が出てからということで。

あいる 2004/07/26(月) 09:25:52
はじめて投稿します。よろしくです。

たまたま同じ環境だったので試してみると同様の症状がでました。

エラー箇所をちょっとみてみると、その直前に・・・
#if (_WIN32_WINNT >= 0x0502)

等の記述が・・・

てなわけで、stdafx.hの設定をちょこっといじってみました。

--- 抜粋

#ifndef WINVER                // Windows 95 および Windows NT 4 
以降のバージョンに固有の機能の使用を許可します。
#define WINVER 0x0500        // これを Windows 98 および Windows 2000 ま
たはそれ以降のバージョン向けに適切な値に変更してください。
#endif

#ifndef _WIN32_WINNT        // Windows NT 4 以降のバージョンに固有の機能
の使用を許可します。
#define _WIN32_WINNT 0x0502        // これを Windows 98 および Windows 2000 ま
たはそれ以降のバージョン向けに適切な値に変更してください。
#endif                        

#ifndef _WIN32_WINDOWS        // Windows 98 以降のバージョンに固有の機能の
使用を許可します。
#define _WIN32_WINDOWS 0x0510 // これを Windows Me またはそれ以降のバージョン向け
に適切な値に変更してください。
#endif

#ifndef _WIN32_IE            // IE 4.0 以降のバージョンに固有の機能の使用を
許可します。
#define _WIN32_IE 0x0500    // これを IE 5.0  またはそれ以降のバージョン向けに適切
な値に変更してください。
#endif

--- 以下略

このようにすると、エラーはでなくなります。

参考になりましたでしょうか?

あいる 2004/07/26(月) 09:34:28
と、送信した後よくみるとなにやら大変なことに気がつきました・・・

> #define _WIN32_WINNT 0x0502        // これを Windows 98 および Windows 2000 ま

これって、Windows Server 2003 family 以降のバージョンってことになりますねぇ・・・
ん〜・・・実質使えないに等しい?

ちなみに、標準環境においては、
#if (_WIN32_WINNT >= 0x0502)

の記述がないためエラーはでませんね。

# PSDKの仕様なんでしょうかねぇ?

三毛猫 2004/07/26(月) 09:38:57
Platform SDK February 2003付属のWS2tcpip.h内では

#ifdef UNICODE
#define FreeAddrInfo    FreeAddrInfoW
#else
#define FreeAddrInfo    FreeAddrInfoA
#endif

の部分が #if (_WIN32_WINNT >= 0x0502) で括られていました。
VisualStudio.NET2003付属のWS2tcpip.hではこの記述がないので、

> Platform SDK February 2003 をインストールしてあり、インクルードディレクトリは
> VC++ 付属のものよりも、これらが優先されるようにしてあります。

というのが原因ではないでしょうか。
(どちらが正しいのかは良く分かりませんが)

シャノン@会社からカキカキ 2004/07/26(月) 10:08:45
会社でも同じビルドエラー出ました。

> エラー箇所をちょっとみてみると、その直前に・・・
> #if (_WIN32_WINNT >= 0x0502)
> 等の記述が・・・
> てなわけで、stdafx.hの設定をちょこっといじってみました。
> このようにすると、エラーはでなくなります。

レスありがとうございます。
確かにその通りにすると、エラーは消えました。
#そのくらい、AppWizard で定義しといて欲しいもんですが。

ところで、Windows NT のバージョン 5.2 って何? と思って調べたら
Windows Server 2003 のことらしいですね(※1。

これについて、問題点が3つ。
「MSDN には WinXP から使えるって書いてあるやんけ!(※2」ってことと
「SP1 から使えるなら SP1 からって書いとけや!(※3」ってことと、
「WinXP 以前の OS だと、AppWizard で『Windows ソケット』使えませんって書いとけ
や!(※4」ってこと。

ミスだと思うんですけどね…どこに言えばいいのかな。

※1
http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/winprog/winprog/using_the_windows_headers.asp

※2
VS.NET 2003 付属の MSDN にも、Platform SDK 2003.02 にも、

> Client: Included in Windows XP.
> Server: Included in Windows Server 2003.

と。
ところが、MSDN Online

http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/winsock/winsock/getaddrinfo_2.asp

では、

> Client: Requires Windows XP, Windows 2000 Professional, Windows NT 
Workstation, Windows Me, Windows 98, or Windows 95.
> Server: Requires Windows Server 2003, Windows 2000 Server, or Windows NT 
Server.

どっちなんじゃーい!

※3
※1 のページの下のほうに
「サービスパックで追加される機能もあるから、ターゲットが XP だからって 0x0501 
って定義しとくと見逃すよ」
みたいな一文が。
でも、XP SP1 から使える関数は、MSDN にもしっかり「SP1 から」って書いてあるのも
あるのに…

※4
実際には、実行時に動的リンクされるので、Win2000 + IPv6 Technology Preview でも
使えるけど… _WIN32_WINNT 0x0502 を定義させるのはよろしくない、と思う。

シャノン@会社からカキカキ 2004/07/26(月) 10:16:47
↑勝手に折り返されて見づらい部分もありますが、脳内補完してください。

レス書いてる間にさらにレスが!
ありがとうございますー。

VS.NET 2003 付属のヘッダには #if が…あ、ほんとだ。無い。
何なんでしょうね、まったく…

シャノン@会社からカキカキ 2004/07/26(月) 10:25:02
[[解決]]
結論。
皆様のおかげで原因も特定でき、俺の環境が悪いわけでもない(PSDK インストールして
あることが「環境が悪い」だったらお笑いだ)ということもわかったので、解決といた
します。
ありがとうございました。

ところで…

・AppWizard で『Windows ソケット』にチェックを入れる場合は 0x0502 定義しておか
 ねばならんというのを明記すべき(MFC チームと PSDK チームの齟齬が原因か? し
 っかりしてくれよ…)。

・AppWizard のヘルプにでも、『Windows ソケット』にチェック入れるのは WinXP 以降
 でしかダメ( Win2000 + IPv6 Technology Preview でもいけるかも)と明記すべき。

・結局、GetAddrInfo の対象 OS はどれなの!?

という3点を MS に訴えたいところでした。
窓口どこかなぁ…

あいる 2004/07/26(月) 10:36:18
> #そのくらい、AppWizard で定義しといて欲しいもんですが。
といっても、PSDKにはAppWizardのテンプレートが付属されてないですから、
VC++.NETで対応されてなくても、ここは仕方ないかと・・・
# そのくらいつけとけ!って、話もありますがw

それはさておき・・・
_WIN32_WINNT 0x0502 とされていないと機能しないものをさがしてみましたが・・・
ふむ・・・WinBase.h と

あいる 2004/07/26(月) 10:44:00
う・・・途中になっちゃった(汗

WinBase.h と WS2tcpip.h だけ _WIN32_WINNT >= 0x0502
なようですね。

ソケットライブラリが実行時にリンクされ、動作的に問題がないのであれば、
_WIN32_WINNT 0x0502 は問題なさそうです。

# ま〜・・・その状態で WINVER 0x0500 が正しいかもわかりませんが・・・

>> Client: Requires Windows XP, Windows 2000 Professional, Windows NT 
>Workstation, Windows Me, Windows 98, or Windows 95.
>> Server: Requires Windows Server 2003, Windows 2000 Server, or Windows NT 
>Server.
>
>どっちなんじゃーい!

の記述があるのだから、WINVER 0x0500 にしておけば、とりあえずPSDK使用でも大丈夫そうに
思えます。
その代わり、staticリンクはご法度になりますが・・・

# 私なら、たぶん前述した stdafx.h の書き方で実装しちゃいます。
# 環境デバッグして動作がまずいようなら、PSDKはずしてリリースしちゃえばいいのでw

シャノン@会社からカキカキ 2004/07/26(月) 11:21:01
> ソケットライブラリが実行時にリンクされ、動作的に問題がないのであれば、
> _WIN32_WINNT 0x0502 は問題なさそうです。

> その代わり、staticリンクはご法度になりますが・・・

WSpiApi.h ってファイルを見ると、IPv6 関連のモジュールを動的ロードしているコード
が見つかります。
これは、WinXP SP1 より前の IPv6 サポートは評価版のようなもので、ws2_32.dll には
実装されていなかったためかと思いますが、これが思いがけず功を奏し、0x0502 を定義
しておきながら実際にはサポートしていなかった場合にも対応…してないっ、こいつし
てないよ!
たぶん、IPv6 未サポート(WinXP SP1 より前の環境で、IPv6 Technology Preview イン
ストールされて無い)環境では、落ちるような気がする。

あいる 2004/07/26(月) 12:01:05
動的ロードの部分は WspiapiLoad 関数のとこですよね?
これをみると・・・

まず、WS2_32.dllを 探す。そこに getaddrinfo があったら抜ける。
なかったら、 wship6.dll を探す。そこにgetaddrinfo があったら抜ける。
どっちにもなかったら、WSPIAPI_FUNCTION_ARRAYを使うと・・・

もしかして、WSPIAPI_FUNCTION_ARRAY がまともに動作しない??
# Diff とってみた感じでは、WSpiApi.h の記述自体に差はないようにみえるけど・・・
# 時間あるときにここは検証しておかないと、後で泣きそうだから今度やっておこうっと・・・
# さすがに、現状の情勢だとXPSP1以降でないと動きませんってアプリは出せない・・・(泣

としたら、ソケット使うにはPSDK使うなと・・・?
それはそれでなんかいやな感じですねぇ・・・

# まぁ、0x0502 定義にすると、0x0501 が大量に引っかかるので、
# 実行時にバージョンチェックして、動作の振り分けしないといけないとことかでてくるかもな
ので、
# 別なところで大変になるなぁ・・・とは思っています
# しかし、XPSP1以降でないとなんて・・・PSDKの使用も微妙な感じですねぇ

シャノン@会社からカキカキ 2004/07/26(月) 12:08:13
> どっちにもなかったら、WSPIAPI_FUNCTION_ARRAYを使うと・・

ごめん、それ使ってたか。気づきませんでした。

> 0x0502 を定義しておきながら実際にはサポートしていなかった場合にも対応…
> してないっ、こいつしてないよ!

これは撤回で。すいませんでした。

てことはつまり、
XPSP1 だか 2003 だかでサポートされてる(ws2_32 に組み込まれてる)のはネイティブ
なもので IPv6 をサポートしてて、
SP なし XP と 2000 では IPv6 Technology Preview(WSHIP6.DLL)がインストールされ
てればそれを使って、
どちらもない場合は…IPv4 しかサポートしないかもしれないけど、それでもいいなら

> Client: Requires Windows XP, Windows 2000 Professional,
>         Windows NT Workstation, Windows Me, Windows 98, or Windows 95.
> Server: Requires Windows Server 2003, Windows 2000 Server,
>         or Windows NT Server.

これをすべて満たすのかもしれない、と。

あいる 2004/07/26(月) 13:44:37
そんなわけで実験してみました。

コードを追加っと・・・
CSocketAddr sock;
とりあえず、1行いれてみて実行っと

結果・・・

「プロシージャエントリポイントfreeaddrinfoがダイナミックライブラリWS2_32.dllから見つ
かりませんでした。」

・・・。

使えませんね・・・(涙
それとも、単に環境が整ってないだけ?
ちなみに、Windows2000SP4 で実行してみました。

てなわけで、PSDKをはずして実行・・・
同じメッセージですか・・・。
CSocketAddr が使えない??試しにnewしても・・・同じですね。

んじゃ、

----
    int err;
    addrinfo hints, *res0;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = PF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    /* getaddrinfo で、AAAAおよびAレコードを取得*/
    err = getaddrinfo("hogehoge.org", "http", &hints, &res0);
    if (err) {
        fprintf(stderr, "error : %s", gai_strerror(err));
        freeaddrinfo(res0);
        exit(1);
    }
    freeaddrinfo(res0);

----

としてみると・・・
また同じ・・・(涙

ん〜・・・これは完全に環境できてない?
今日は時間ないので、ここまで・・・
ちゃんと環境用意しないと実験できないや・・・
# というか、WspiapiLoadにブレークしかけても、とまらないのよね・・・
# もしかして(もしかしなくても)、ここに来る以前ではじかれちゃってるのかな〜
# 気になるけど、お昼終わっちゃったから・・・おうち帰ってから眠くなかったらまた実験しま
す・・・(涙

シャノン 2004/07/26(月) 14:40:03
これかなー?

http://support.microsoft.com/default.aspx?scid=kb;JA;822334

あいる 2004/07/26(月) 16:55:32
それは関係ないっぽいですねぇ・・・
というか、それ以前に私のWS2_32.dllにfreeaddrinfoがみあたらないですし
(Dependency Walkerで確認した感じ)

それはそれとしてws2tcpip.hの最後にこんな記述が・・・

#if !defined(_WIN32_WINNT) || (_WIN32_WINNT <= 0x0500)
#include <wspiapi.h>
#endif

・・・。
これでは、_WIN32_WINNT 0x0502 を定義した時点で使われないですね・・・
0x0500だとコンパイルエラーなのに、これはひどい仕打ちです(涙

PSDKソースをいろいろ見た結果・・・
結局シャノンさんの最初の対応どおりで良さそうですね。

stdafx.hの
#include <afxsock.h>        // MFC のソケット拡張機能
の部分を

#define GetAddrInfo    getaddrinfo
#define FreeAddrInfo   freeaddrinfo
#include <afxsock.h>        // MFC のソケット拡張機能

とするで・・・
Windows2000等でも動作するものになりそうです。

# CListCtrl や CTreeCtrl とかもそうでしたけど、PG側で再定義しないと
# 使えないライブラリって・・・人の書いたものですしそんなもんですかねぇ・・・

# ちなみに、サンプルChatSrvrは_WIN32_WINNT等のバージョン書き換えだけで
# 問題なく動作しました。どうやらCSocketAddrとか、そのあたりを使用するとき
# に注意が必要なようですね。
# ちなみに、defineを追加するときは_WIN32_WINNT 0x0500でないとまずいですが・・・

# あ、ATLを使わないで記述する分には・・・このdefineとかは特に要らないようです。
# afxsock.h や atlsocket.h をインクルードしないってことですね。

古いスレッドには追加発言できません。