VCのエラーメッセージ・メモ
by K.I
Index
- VCでプログラムは初心者なので、エラーに悩まされる。
- 何だかよくわからないエラーばっかりだが、何度も同じ失敗を繰り返すので、
- どんなエラーがあったか、メモしておくことにした。→解決していないものも有り。
- 分からずに書いてるので、意味不明のメモもあり。
- VC5のエラーや、VS2005のエラーが混在しているので注意。VS2017も少し追加している
[top]
- stdafx.hがインクルードされていないファイルがあった。
- '#include "pch.h"' をソースに追加しましたか? と言われる
- プリコンパイル済みヘッダーは使用していないので、
- プロジェクトのプロパティで、C/C++→プリコンパイル済みヘッダーで、プリコンパイル済みヘッダーを使用しない様にした
- 何らかの理由で、includeファイルを開く事が出来ないというエラー。
- まずプロジェクトのソースディレクトリに、本当にそのファイルがあるかどうか確認。
- 別のディレクトリにある場合は、プロジェクトのプロパティ(設定)→C/C++→全般→追加のインクルードディレクトリに設定されているか確認。
- VC5の場合、ツールメニュー→オプション→ディレクトリで指定してみる。
- VC5では、個別にプリコンパイラ済みヘッダーの設定が可能なので、stdafx.hのみ作成するで、後は使用するになっていることを確認する。
- C1083は、自分的には一番嫌いなエラー。環境を変更したりプロジェクトをコピーしたりすると、必ずと言うほど見るし、意外と対応に時間が掛かる。
- あと、上記はVC5,VS2005での話。VC6は分からないけど、おそらくVC5と同様?
- 別のディレクトリにあるファイルをインクルードした時、そのファイルに
#include "stdafx.h" という記述があると、C1083が出ることがある。
- プロジェクトのプロパティ→C/C++→全般→追加のインクルードディレクトリに、
元々のプロジェクトディレクトリ(stdafx.hの場所)も追加しておく。
- 本来、ソースのあるディレクトリの指定は不要だと思うが、何故かこうすると直る。
- stdafx.hを使っている時、コンパイル時にこのエラーが出ることがあった。
- プロジェクトのプロパティで、一旦、プリコンパイル済ヘッダを使用しないにして、リビルド。
- さらに、プリコンパイル済ヘッダを作成するに設定しなおしてから、再度リビルドするとコンパイル出来た。
- 単純に、プリコンパイル済みヘッダを作成するに設定した場合は、ダメ。
C1083対策→相対パス指定
- 例えば、以下のようなディレクトリ構造の時、(VS2005の場合)
- 追加のインクルードディレクトリの指定は、こんな風にする。
- ..\\lib →ライブラリの参照
- .\\baseapp →ソースのあるディレクトリ
- つまり、VS2005\baseappから見て、相対指定すれば良い。
- 同じファイルを2回インクルード、DLLと呼出し側で同じ構造体を定義している場合など。
- その場合は定義を整理して、定義を含むヘッダが先にインクルードされることをチェック。
- Windows.h関連で出る場合は、Includeの順番が関係している場合もある。
- 原因は単純だが、対策は意外と厄介だったりするエラー
- windows.hや、process.hをインクルードしてあるのに、
- '_beginthread'が未定義 となってしまう
- プロジェクトの設定→C/C++→コード生成タブで、
- 使用するランタイムライブラリがマルチスレッドになっていなかった。
- 単純な構文エラーだが、includeしているヘッダファイルにエラーがある場合、分かりづらい場合がある。
include後の関数で、「'int'は';'によって先行されなければならない」となる。
- switch-caseで、型の付いた変数の設定を行うようにしたら出た。
switch (xxxx) {
case 0:
BYTE (Cyyyy::*zzzz)(BYTE) = fname;
break;
}
switch (xxxx) {
case 0: {
BYTE (Cyyyy::*zzzz)(BYTE) = fname;
break;
}
}
- 以下のキャストで出る。出来そうな気がするんだけど。。
typedef union {
WORD w;
BYTE b[2];
} UNIWORD;
UNIWORD udata;
WORD data
udata = (UNIWORD)data;
error C2440: 'type cast' : 'unsigned short' から 'UNIWORD' に変換することはできません。(新しい動作 ; ヘルプを参照)
コンストラクタはソース型を持てません、またはコンストラクタのオーバーロード レゾリューションがあいまいです。
data = (WORD)udata;
error C2440: 'type cast' : 'UNIWORD' から 'unsigned short' に変換することはできません。(新しい動作 ; ヘルプを参照)
この変換を実行可能なユーザー定義変換演算子がないか、または演算子を呼び出せません。
- 共用体を使ったことがないので、使ってみようと思ったんだけど、
- 例えばクラスCxxxxに、以下のような関数と、 関数ポインタを保持するメンバ変数があって、
BYTE fname(BYTE tpara) { ... }
BYTE (*fname_ptr)(BYTE);
- メンバ変数に、 関数ポインタを代入しようとしたら、C2440のエラーとなった。
fname_ptr = fname;
よく分からなかったが、 こちらで、理由が説明されていた。
- メンバ関数には、オブジェクトのポインタも必要なので、これではダメらしい。
- 関数の定義と、ヘッダファイルのプロトタイプ宣言が異なっていると、このエラーが出る。
- 普通はすぐに気が付くが、オーバーロード関数を書いてる時に、別の場所で出て、
- オーバーロードじゃないのに何故?と悩んだことがある。。
- 関数の引数を省略する場合、デフォルト値はプロトタイプ宣言、関数定義のいずれに記述しても良いことになっている。
- が、実際はコンパイル時に必要なので、プロトタイプ宣言(ヘッダ)で記述しないと、このエラーが出る。
- サブクラス化しようとして、CallWindowProcを使った時に出た。
- VC++5では,CallWindowProcの第一引数は基本的にFARPROC型だが、
- VC++6では,基本的にWNDPROC型(MSDNの通り)になる
- とりあえず、マルチバイト文字セットを使用することでエラーは出なくなったが、
- プロジェクト⇒プロパティで、構成プロパティ⇒詳細の 文字セットが
- UniCode文字セットを使用する となっているのを
- マルチバイト文字セットを使用する に変更
- API関数をうまく渡せない。そもそも根本的に渡し方が違うのかも(未解決)
- と思ったけど、テンプレートだったのでメインのソースがなかっただけらしい。。
- pow(10,2)というように記述すると、このエラー。
- VS2005から、ダメになったみたい。
- pow(int,int)は、pow(double,int)のように最初の引数はdoubleにキャストしなければならない。
- クラスで関数ポインタを使ったものを、新しいVisual Studioでコンパイルしたら出るようになった。
error C3867: 'Classname::funcname': 関数呼び出しには引数リストがありません。
メンバーへのポインターを作成するために '&Classname::funcname' を使用してください
- 例えば、こんな風に関数ポインタを代入していた箇所を、
void (Classname::*funcptrname)(BYTE) = funcname;
以下のようにClassnameとアドレス参照であることを明記した
void (Classname::*funcptrname)(BYTE) = &Classname::funcname;
- strcpyを使うと、Visual Studio 2005では、以下のようにWarningになる。
warning C4996: 'strcpy' が古い形式として宣言されました。
strcpyはバッファの長さを指定しないため、メモリリークを起こしやすいので、警告している。
- 以下のように長さを指定出来る関数に書き換えれば良い。
- strcpy(line,"ABC"); → strcpy_s(line,255,"ABC");
- sprintf(line,"%s","ABC"); → sprintf_s(line,255,"%s","ABC");
- sscanf(str,"%lf",&f); → sscanf_s(str,"%lf",&f); →これって何の意味があるんだろうね。
- 但し、とりあえずマルチバイト指定にすれば、このワーニングは一応出なくなる
- でも、Visual Studio 2013でやってみると、これはエラーに昇格していて、マルチバイト指定にしただけではダメみたい。
error C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead.
To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
当然、関数を書き換えればOKのなんだけど、
- 厳密にはconstを付けるべきだが、古いライブラリ等で変更が難しい場合は
- プロジェクト⇒プロパティで、
- C/C++⇒すべてのオプション⇒その他のオプションに
- /Zc:strictStrings- と設定する
[top]
- VC、或いはVisual Studio製品版で作成したプロジェクトを、Wxpress版でコンパイルした時に出力されるエラー
[top]
- 新しいVS2005のライブラリを、VC5でリンクしようとしたら出た。
- やはり、VS2005でコンパイルしないとダメか。。
- 環境を変えて、コンパイルし直したら出るようになった。
- 自分の作ったルーチンだったので、 これのように、/FORCE:MULTIPLE オプションで 無視してしまった。
- 手抜きだ。。。後で、バグるかも。
- DLLを呼出して場合は、DLLファイルがあるかどうか再確認する。
- LIBファイルがプロジェクトで指定されていない場合は、例えば以下のように指定する。
#include <wininet.h>
#pragma comment(lib, "wininet.lib")
- ライブラリがプロジェクトに登録されていない?前述の例と同様に
#pragma comment(lib, "glew32.lib")
- 或いは、プロジェクトのプロパティで、リンカの入力の追加の依存ファイルを確認
自作の関数でget_datetimeという奴が、いつもLNK2001になる。
- 同じファイルに含まれる他の関数は、問題が無い。
- 関数名で右クリックして定義位置を表示させた時に、実際の関数定義が表示されずに、ヘッダファイルのプロトタイプが表示される。(プロトタイプと関数定義の差異は無い)
- 仕方がないので、呼び出し側でも2重定義して対応している。(2重定義エラーは出ない)
- includeがうまく出来ないと思われるが、同じファイルの他の関数との差異が分からない。
- 未だに原因不明。
DLLを使った時に、以下のエラー
xr_chart.obj : error LNK2001: 外部シンボル ""__declspec(dllimport) int __cdecl kMsgBox(char const *,unsigned int,char const *,...)" (__imp_?kMsgBox@@YAHPBDI0ZZ)" は未解決です
#ifdef __cplusplus
# define DLLImport extern "C" __declspec( dllimport )
#else
# define DLLImport __declspec( dllimport )
#endif
でもまだ出る。
xr_chart.obj : error LNK2001: 外部シンボル "__imp__kMsgBox" は未解決です
これは単に、チェックしていた箇所と別の場所で定義せずに呼んでいるためだった。
cppとcを混在させた時に、LNK2001のエラー
- CとC++は呼出し規約が違うので、Cの関数にはextern "C"を付けなければならないらしい。
- とりあえず、Cプログラムのファイル名の拡張子を.cppに変更したら通った。
- 開発環境を変えた時に、今まで動いていたプロジェクトでリンクエラー。
nafxcwd.lib(afxmem.obj) : error LNK2005:
"void __cdecl operator delete(void *)"(xxxx) already defined in LIBCMTD.lib(dbgnew.obj)
- 英語なので、良く分からないけど、VC6の場合は2つ方法があって、1つの方法は、
- Ignore librariesで、Nafxcwd.libとLibcmtd.libを指定
- Object/library moduleで、Nafxcwd.libとLibcmtd.libを指定
ということらしい。(未確認)
- .NETの場合は、なんかちょっと複雑な手順が書いてあって理解不能なので、 リンク参照
- プロジェクト⇒プロパティで、リンカー⇒すべてのオプションの サブシステムが
- コンソール(/SUBSYSTEM:CONSOLE)になっているのを
- Windows(/SUBSYSTEM:WINDOWS)に変更
- プロジェクトの設定の問題かと思って、新規でプロジェクト作り直したりしても駄目。
- 結局、tchar.hをインクルードしてないのが原因だった。
http://d.hatena.ne.jp/matobow/20061107/p1
[top]
- /NODEFAULTLIB:library を使用してください。
- Releaseでビルドする時は、Release用のライブラリ、
- Debugでビルドする時は、Debug用のライブラリをリンクしなくちゃいけないらしい
- Warningだが、実行時に落ちることがあるので対処が必要
[top]
- 確保しているメモリ以外を参照した場合。
- 例えば、str255でバッファと取っていて、str255の変数を複数詰め込んだりした時
- printf的な関数を作る時に、良く起こる。
- printfの書式設定ミスでも起こったりするが、これは結構やってしまう。
- アクセスバイオレーションが起こっている場所を見つけるのは至難の業だが、
- VCなら、デバッガで実行して落ちた後に、表示→デバッグウィンドウ→コールスタックで呼ばれた関数が分かるので、それで見当が付けられる場合がある。
- 割り当てられていないメモリにアクセスしようとした場合に起こる
- ポインタの値がおかしいとか重大なエラーだけど、見つけるのが難しい。
- 動いていたプログラムが、違う環境でこのエラーが出たりする。
- 再コンパイルで直ったりすることもあるが、隠れたバグが出ている場合も多い。とっても嫌なエラー。
- ちょっとエラー箇所が分かりにくい場合がある。
- このDialogが出たら再試行ボタンを押して、デバッガが止まった場所から考える。
- 例えば、CListCtrlで、OwnerDrawFixedにしてるのにDrawItemが無いとか。
- ローカル変数は、スタック上に確保されるが、VCではスタックはデフォルトで1MBしか無い。
- 大きなデータは、自分で動的に確保するか、グローバル変数にすること。
- Windows2000で、動作しているプログラムが、WindowsXPで、以下のDialog
アプリケーションを正しく初期化できませんでした。0xc0000005
原因不明だったが、検索すると、WindwosUpdateやドライバの再インストールで直った例があったので、
- 半信半疑で、試しにWindowsUpdateしたら、直った。。。
- これはちょっと違うが、COMポートの通信プログラムで、
- この場合、無効なハンドルということらしい。
- LoadLibraryで、DLLを読込む時にDLLが存在するのにNULLが返って来ることがある。
- この場合は、DLL内で使用しているDLLが存在しな場合がある。
- DependencyWakerを使えば、DLLが使用しているDLLの一覧を確認できる。
- 非同期通信で、受信用スレッドを作ってWaitCommEventで待つようにしたら、
- 別スレッドで送信すると、WaitCommEventで87のエラーになる。
- 受信だけならば特に問題ない。
- 87はInvalidParameterだが、パラメータはチェックしても問題なさそう。
- このプログラムでは、送受信用のハンドルを作って、送受信兼用で使っていた。、
- もしかすると、これは同時に送受信を行ってはいけないのかもしれない。
- 同時に行うためには、送信・受信で別々のハンドルを用意する必要があるのかも。
- とりあえず送信データを保存して、WaitCommEvent待ちが終わってから、送信するようにしたら問題無くなった。
- fopenは、Read時にファイルが無ければ、当然NULLを返す。
- でも、Write時にNULLを返したので、ちょっと悩んでしまった。
- そのfopenは、処理した結果を最後に保存するために新規にOpenしているだけだが、
- 処理するデータが大きくなると、何故かNULLを返すようになる。
- ファイル名が、Windowsの規則に合わないとかなら、エラーになるだろうけど問題なし。
- DiskFull(ディスク容量が一杯)になっているワケでもないし。。
- データ処理がメモリリークを起こしているのかと思って調べたが、ナカナカ分からず。
- 結局、原因はデータ処理のデバッグ用に中間ファイルを作っていたが、そこでfcloseしていなかった。
- 同じファイル名で、数百回fopenして、fcloseしていなかったためだった。→400回ちょっとでNULLになっていた
- その部分は、コメントアウトしたつもりだったが、fopenだけ抜けていた。
- ここではfopenだけしていたので、ここでNULLになっているのに気が付かなかった。
- レジストリのある項目の読出しに失敗する理由が分からず悩んでいた。
rc= RegOpenKeyEx(parent_key,sub_key, 0,KEY_ALL_ACCESS,KEY_READ,&hKey);
if (rc!=ERROR_SUCCESS) error();
rc= RegQueryValueEx(hKey,szName,NULL,&dwType, (BYTE *)szValue,&dwByte); RegCloseKey(hKey);
if (rc!=ERROR_SUCCESS) error();
という感じなんだけど、RegQueryValueExが失敗することがある。
- 同じキー名でも、読めるものと読めないものがあるのが良く分からない。
- 諦めていたんだけど、 こちらの情報で、2度読むやり方が書いてあったので、だめもとで試してみたら、全く問題なく読めるようになった。
rc= RegOpenKeyEx(parent_key,sub_key, 0,KEY_ALL_ACCESS,KEY_READ,&hKey);
if (rc!=ERROR_SUCCESS) error();
rc= RegQueryValueEx(hKey,szName,NULL,&dwType, NULL,&dwByte); // 1回目はサイズ取得のみ
rc= RegQueryValueEx(hKey,szName,NULL,&dwType, (BYTE *)szValue,&dwByte); RegCloseKey(hKey); // 2回目に実際に取得
if (rc!=ERROR_SUCCESS) error();
- atofの結果を見ると、常に-1になってしまう。
- これは、単に #include <stdlib.h> を忘れただけだった。
- エラーにはならないので、気が付きにくい。
- ちょっと馬鹿馬鹿しい間違いなんだけど、なんか続けてやっちゃったので記録する。
- でも、これはVCじゃなくて、gccの場合だけかもしれない。
- 実績のある、ライブラリ内の関数をテスト的に外で使ってみたら、戻り値がおかしい。
- 結果が 1072693248で、戻り値に拘わらず、いつも同じ
- 型が合ってないみたいに見えるが、関数を同じファイル内で定義すると問題ないし、関数を削除するとエラーになるし
- 結局、ヘッダファイルにプロトタイプを書き忘れていた。
- プロトタイプのない関数は、intと仮定してコンパイルされるらしい
- 常識らしいが、いままで知らなかった。(新規作成の時はすぐにプロトタイプ書くので。。)
- くだらないことだが、自戒として記録
- gccだったので、VCだとwarningでるのかもしれない。
- F5でデバッグ実行すると、コンパイルは出来ているのに、以下の様なDialogが出る
プログラム 'C:\xxxx\.\Debug\xxxx.exe'を開始できません。
指定されたファイルが見つかりません。
- リンカの出力ファイルは、プロジェクトのプロパティで設定出来るが、デバッグ実行時のファイル名は、プロジェクト名.exeになる
- プロジェクト名と、リンカ出力ファイル名は一致させておく必要があるらしい。
[top]
[プログラムの部屋に戻る]