はじめまして、sandayu999と申します。
ネットワークアダプタの情報を取得するために
GetAdapterInfo関数を使用しているのですが
返り値がエラーとなってしまいます。
環境はWindowsXPでCコンパイラは
borlandのbcc32.exeを使用しております。
コンパイルは正常に行えました。
[mac.c]
---------------------------------------
IP_ADAPTER_INFO adapterInfo;
DWORD aiSize;
GetAdaptersInfo(NULL,&aiSize); //サイズ取得
print("%d\n",GetAdaptersInfo( &adapterInfo, &aiSize ));
出力してみたところ、値が87(ERROR_INVALID_PARAMETER)
となってしまいました。
どのような対処をしたら良いのかわからない状態です、どなたかアドバイスをよろしくお願いいたします。
No.3ベストアンサー
- 回答日時:
PIP_ADAPTER_INFO padapterInfo;
DWORD aiSize;
GetAdaptersInfo(NULL,&aiSize);
padapterInfo=(PIP_ADAPTER_INFO)malloc(aiSize);
printf("%d\n",GetAdaptersInfo( padapterInfo, &aiSize ));
free(padapterInfo);
でどうでしょう?
質問文のソースではアダプタが1つの時にしか正常に動作しないような気がします。
この回答への補足
hofuhofuさん、taka_tetsuさん返信ありがとうございます。
>taka_tetsuさん
>書かれているコード、質問に書かれた部分で全部ですか?
すみません、一部しか記述しておりませんでした。
全体は下記になります(多少みずらくなってます)
-----------------
#include <windows.h>
#include <iphlpapi.h>
#include <stdio.h>
void main(void){
IP_ADAPTER_INFO adapterInfo;
DWORD aiSize, i;
GetAdaptersInfo(NULL,&aiSize);
if( GetAdaptersInfo( &adapterInfo, &aiSize ) != ERROR_SUCCESS )
{
printf( "GetAdapterInfo呼び出し失敗\n" );
return;
}
fprintf( stdout,"MACアドレス = [" );
for( i = 0; i < adapterInfo.AddressLength; i++ )
{
fprintf( stdout, "%.2X", (int)adapterInfo.Address[i] );
if( i == ( adapterInfo.AddressLength - 1 ) )
fputs( "]\n", stdout );
else
fputs( "-", stdout );
}
}
そこで、hofuhofuさんのご指摘通りに行ってみたところ、
-----------------
PIP_ADAPTER_INFO padapterInfo;
DWORD aiSize;
GetAdaptersInfo(NULL,&aiSize);
padapterInfo=(PIP_ADAPTER_INFO)malloc(aiSize);
printf("%d\n",GetAdaptersInfo( padapterInfo, &aiSize ));
free(padapterInfo);
にて成功の0が出力されました。
これはIP_ADAPTER_INFOのポインタ型のPIP_ADAPTER_INFOを使用することでNIC分のメモリを
確保しているという解釈でよいでしょうか?
(IP_ADAPTER_INFOだと、一つ分しか確保できていなかった)
そこで、プログラムを下記のように直してみました。
-----------------
#include <windows.h>
#include <iphlpapi.h>
#include <stdio.h>
void main(void){
PIP_ADAPTER_INFO padapterInfo;
DWORD aiSize, i;
GetAdaptersInfo(NULL,&aiSize);
if( GetAdaptersInfo( padapterInfo, &aiSize ) != ERROR_SUCCESS )
{
printf( "GetAdapterInfo呼び出し失敗\n" );
return;
}
while( padapterInfo )
{
fprintf( stdout,"MACアドレス = [" );
for( i = 0; i < padapterInfo->AddressLength; i++ )
{
fprintf( stdout, "%.2X", (int)padapterInfo->Address[i] );
if( i == ( padapterInfo->AddressLength - 1 ) )
fputs( "]\n", stdout );
else
fputs( "-", stdout );
}
padapterInfo = padapterInfo->Next;
}
free(padapterInfo);
}
[結果]
-----------------
MACアドレス = [00-xx-xx-xx-xx-xx]
MACアドレス = [00-xx-xx-xx-xx-xx]
MACアドレス = [00-xx-xx-xx-xx-xx]
と無事MACアドレスが出力されました。
雑誌にはもともとのソースでもNIC1枚分の情報は出力
されるとあったのですが、現在の方法
での処理のほうが正しいようです。
それと、MSDNのサンプルでは
http://msdn.microsoft.com/library/default.asp?ur …
でIP_ADAPTER_INFOのサンプルを見てみたのですが、
こちらはFREE関数を使ってメモリを最後に開放していないのですが、これはサンプルだから省略されたということでしょうか?
通常は、hohuhohuさんの書かれるとおり、最後にFREE
を入れるべきですよね?
No.6
- 回答日時:
ちょっと修正です。
aiSizeを初期化もせずにつかっているのがまずいです。
本来この手法はOutBufLenに0を指定して、強制的にERROR_BUFFER_OVERFLOWを起こし必要な領域のサイズを得ようというもののようです(このときpAdapterInfoは問題にならないのでNULLを入れている)。
MSDNのサンプルソースではアダプタが複数あった場合にのみ発生したERROR_BUFFER_OVERFLOWを処理しているのに対し、最初からERROR_BUFFER_OVERFLOWを前提にしてプログラムを組んでいるという違いがあります。
ただpAdapterInfoにNULLを指定した場合にもOutBufLenの値に関係なくERROR_BUFFER_OVERFLOWが発生し、OutBufLenに必要な領域のサイズが帰ってきているようです。
今回のケースではこの現象により正常に動いているように見えていたわけですが、MSDNにはERROR_BUFFER_OVERFLOWの発生条件としてOutBufLenが小さすぎること以外書かれていないので、この現象に依存したプログラムは避けるべきだと思います。
hohuhohuさん返信有難うございます。
なるほど、確かに自分のソースは最初からERROR_BUFFER_OVERFLOWをさせて取得しています。
(初期化もせずに)
MSDNのソースに直した形での取得方法にしようと
思います。
No.5
- 回答日時:
> これはIP_ADAPTER_INFOのポインタ型のPIP_ADAPTER_INFOを使用することでNIC分のメモリを
> 確保しているという解釈でよいでしょうか?
MSDNを見る限りそういうことだろうと判断して回答しました。
説明文を読むと十分な領域さえ確保されていれば、サイズはどのような値でもいいようです。
BYTE buf[5120];
DWORD aiSize=5120;
GetAdaptersInfo((PIP_ADAPTER_INFO)buf,&aiSize);
でもほとんどの環境で正常に動作すると思います。
それより改めて見直してみて気になったのは、
GetAdaptersInfo(NULL,&aiSize); //サイズ取得
ですね。
確かに必要な容量がaiSizeに帰ってきていますが、この挙動自体はMSDNに記載されていないようです。
If this size is insufficient to hold the adapter information, GetAdaptersInfo fills in this variable with the required size, and returns an error code of ERROR_BUFFER_OVERFLOW
とはありますが、これはpOutBufLenで指定された値が必要な容量未満だったときですし。
この方法でサイズ取得するのはよく行われているようですが、記載が無い以上避けておいたほうがいいように思います。
この回答への補足
hofuhofuさん、返信ありがとうございます。
>それより改めて見直してみて気になったのは、
>GetAdaptersInfo(NULL,&aiSize); //サイズ取得
>ですね。
>確かに必要な容量がaiSizeに帰ってきていますが、
>この挙動自体はMSDNに記載されていないようです。
MSDNのサンプルを見てみたのですが、
pAdapterInfo = (IP_ADAPTER_INFO *) malloc( sizeof(IP_ADAPTER_INFO) );
ulOutBufLen = sizeof(IP_ADAPTER_INFO);
if (GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS) {
GlobalFree (pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *) malloc (ulOutBufLen);
}
この記述をみると、最初は、
IP_ADAPTER_INFO一つ分で確保しに行ってますが、
そのとき、if文で
GetAdaptersInfo( pAdapterInfo, &ulOutBufLen)
をして、失敗だったらulOutBufLenを使用して
再度所得しなおしているので、MSDN上いちおう
問題ないのではないでしょうか?
No.4
- 回答日時:
>こちらはFREE関数を使ってメモリを最後に開放していないのですが、これはサンプルだから省略されたということでしょうか?
>通常は、hohuhohuさんの書かれるとおり、最後にFREE
を入れるべきですよね?
当たり前のことですが、free()を呼ぶのはその領域が不要になったとき。
MSDNのサンプル、関数にはなってないですよね。
取得したMACアドレス、printfで表示するだけでしたらすぐにfreeしてもいいですけど、他にも使うんでしたら解放しちゃまずいですよね。
taka_tetsuさん返信ありがとうございます。
>当たり前のことですが、free()を呼ぶのはその領域
>が不要になったとき。
>MSDNのサンプル、関数にはなってないですよね。
>取得したMACアドレス、printfで表示するだけでし
>たらすぐにfreeしてもいいですけど、他にも使うん
>でしたら解放しちゃまずいですよね。
なるほど、確かに関数になっていませんでした。
プログラムも理解することができました。
ありがとうございました。
No.2
- 回答日時:
>実際、自分のプログラム(雑誌に載っていたサンプル)
>だとなぜエラーなのか原因がわからなかったのです。
書かれているコード、質問に書かれた部分で全部ですか?
使用してる変数の宣言からAPIの呼び出しまでの間を全部書いていただければどこがおかしいか確認できると思いますけど。
>ERROR_INVALID_PARAMETERについても英語で説明
>はありますが、、いまいち対処法をみいだすことが
>できなくて。
ERROR_INVALID_PARAMETERは、「パラメータが間違ってます」ってだけなんで、使い方が違うとしか言いようが無いです。
No.1
- 回答日時:
taka_tetsuさん、返信ありがとうございます。
実は、自分も調べていて紹介していただいたURL
にはいったのですが、
実際、自分のプログラム(雑誌に載っていたサンプル)
だとなぜエラーなのか原因がわからなかったのです。
ERROR_INVALID_PARAMETERについても英語で説明
はありますが、、いまいち対処法をみいだすことが
できなくて。
他にも、色々と調べてはみたのですが、
ERROR_INVALID_PARAMETER
が出力されてしまっている状態です。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- PHP if(preg_match("/[^0-9]/",$gu_d)){意味を教えてください。 1 2022/05/06 05:37
- PHP phpのエラーについて 1 2022/06/27 22:30
- その他(コンピューター・テクノロジー) 【Tableau Desktop】文字列から8桁の数字を日付型(yyyyMMdd)として取得 1 2023/07/31 10:17
- オープンソース Python openpyxlを使用したセル番地の使用について 1 2023/08/03 22:05
- Visual Basic(VBA) VBA 改行コードの取り方 1 2022/03/22 14:14
- その他(プログラミング・Web制作) pythonでクラスで複数のメソッドを利用する方法 2 2022/04/15 04:17
- Excel(エクセル) EXCELの外部データ取得ができない 1 2023/03/23 09:03
- FX・外国為替取引 MQL5にて謎のエラーが発生!だれか対処を教えてください! 1 2023/03/25 15:59
- PHP $_SESSIONに渡した後はそのまま使っても問題ありませんか? 3 2022/11/08 22:17
- オープンソース ChatGPTをスプレッドシートと連携して自動でリサーチしたいんですがうまく出来ません。。。 1 2023/05/05 15:59
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語で、メモリを解放しないで...
-
メモリのセグメント違反の解決...
-
VBAの配列サイズとメモリに関して
-
【C言語】再帰が時間がかかる...
-
メモリアロケーション異常の発...
-
C言語初心者です。debug assert...
-
エクセルVBA 大容量CSVファイル...
-
Javaでメモリ不足を引き起こす方法
-
CImage::ReleaseDC()のエラーで...
-
メモリ不足
-
プログラムの最大メモリ消費量...
-
メモリの消費量について
-
これて逆じゃないですか?
-
大容量のメモリ確保をスワップ...
-
Apacheでバーチャルホストの最...
-
非再入可能なプログラム
-
「memcpy」と「strcpy」について
-
ファミコンって8ビットしかない...
-
動的メモリとexit(C言語)
-
動的確保できるメモリ容量
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語で、メモリを解放しないで...
-
VBAの配列サイズとメモリに関して
-
【C言語】再帰が時間がかかる...
-
C言語における再帰呼び出しの...
-
メモリが不足しています(VBA)
-
メモリのセグメント違反の解決...
-
メモリ不足
-
エクセル キャッシュメモリー...
-
ファイルマッピング関数で失敗
-
動的メモリとexit(C言語)
-
エクセルVBA 大容量CSVファイル...
-
メモリの解放の仕方
-
「ヒープサイズの設定」て何?
-
EXCEL-VBAにてADOのレコードセ...
-
LoadLibraryしたらFreeLibrary
-
マインスイーパ、自動解析プロ...
-
バッチファイルでの実行EXEのメ...
-
C言語:関数のメモリ上でのサイ...
-
エクセルのメモリ使用状況/Appl...
-
大容量のメモリ確保をスワップ...
おすすめ情報