Windows XPでのプログラムエラーの原因と解決方法

このQ&Aのポイント
  • Windows XPでプログラムエラーが発生し、特にswprintf関数でのアクセス違反が問題となっている。
  • GetModuleFileName関数を使用して実行中のプロセスのパスを取得し、swprintf関数でファイル情報を取得しようとしているが、エラーが発生している。
  • swprintf関数の使い方を調べてもエラーが解消されないため、別の解決策を模索する必要がある。
回答を見る
  • ベストアンサー

環境:Windows XP

環境:Windows XP 言語:Visual C++ 2008 Express Edition 出来る限り自分で解決したくて質問を控えていたのですが…。もう我慢できない、質問します。 ここ4日ほど、毎日学校から帰宅後夜中まで以下のこんな短いプログラムのバグと戦っています(それでもこの4日でだいぶ改善されたほう)。 ソースは、GreenPadというオープンソースのソフトウェア(http://www.kmonos.net/lib/gp.ja.html)を改造したものです。 GreenPadデフォルトからの変更点は、いくつかのインクルードファイルを追加したことと、リソースヘッダ、リソースファイルを編集し、tkad_compile()という関数を呼び出せるようにしたことです。 上記の関数はGppMain.cppに記述しました。 そして問題のプログラムがこちらです。 void GreenPadWnd::tkad_compile() { TCHAR szPath[_MAX_PATH]; TCHAR szDrive[_MAX_DRIVE]; TCHAR szDir[_MAX_DIR]; TCHAR szFileName[_MAX_FNAME]; TCHAR szExt[_MAX_EXT]; TCHAR szOutput[_MAX_PATH * 5 + 1024]; DWORD dwRet=0; //初期化 wmemset(szPath, 0x00, _countof(szPath)); wmemset(szDrive, 0x00, _countof(szDrive)); wmemset(szDir, 0x00, _countof(szDir)); wmemset(szFileName, 0x00, _countof(szFileName)); wmemset(szExt, 0x00, _countof(szExt)); wmemset(szOutput, 0x00, _countof(szOutput)); //実行中のプロセスのフルパス名を取得する dwRet = GetModuleFileName(NULL, szPath, _countof(szPath)); if(dwRet == 0) { MessageBox(NULL, szPath, TEXT("GetModuleFileName 失敗しました"), MB_OK); return; } _tsplitpath_s(szPath, szDrive,_countof(szDrive), szDir,_countof(szDir), szFileName,_countof(szFileName), szExt,_countof(szExt)); swprintf(szOutput,L"実行しているプログラムのフルパス名%s\r\nドライブ%s\r\nディレクトリ%s\r\nファイル名%s\r\n拡張子%s", szPath, szDrive, szDir, szFileName, szExt); } どうしても最後のswprintfでアクセス違反となってしまいます。 何故でしょうか? sqprintfの使い方が乗っているサイトを調べて、そのままコピペでもエラーでるんです。。 例えばこんなソースを拾ってそのまま使っても TCHAR buf[32]; swprintf(buf, L"%d\n", 123); だめでした。

質問者が選んだベストアンサー

  • ベストアンサー
  • jgk
  • ベストアンサー率75% (104/138)
回答No.2

このプログラム(GreenPad)はCRTのスタートアップルーチンを実行しませんので、 C言語の関数(たぶんC++の関数も)を呼んではいけません。 ですので、CRTのスタートアップルーチンを実行するか、 CRT関数相当の関数を自作するか、CRTを使用しないCRT関数相当の関数をどこからか持ってくるしか無いでしょう。 プリプロセッサの定義からSUPERTINYを取り除けば、スタートアップルーチンが実行されるようになりC言語の関数が使用可能になりますが、 このプログラムがCRTを全く使用しないことを前提に設計されているようですので、今回のようなよく分からないトラブルが発生するかもしれません。 例えば、スレッドの生成関係がCRTに対応してないので、生成したスレッド内で、CRTの関数を使用した場合、メモリーリークが発生したりします。 自作またはどこからか持ってくるというのであれば、 Win32APIにwsprintfが有りますので、それでswprintfを置き換えるという手もあります。 wmemset、_tsplitpath_sはエラーになっていませんが、鼻から悪魔から飛び出しても構わないというのでなければ、自作orどこからか持ってくる必要があります。

その他の回答 (1)

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

>どうしても最後のswprintfでアクセス違反となってしまいます。 >何故でしょうか? 引数間違っているから…かと。 ワーニング出ませんでしたか? http://msdn.microsoft.com/ja-jp/library/ybk95axf(VS.80).aspx 第2引数は「size_t型」ですよね? wchar_t *型渡したらワーニング(かエラー)出そうなモノですが……。 記述されている引数だとsprintf()ですかね。(_MBCSの場合ですが…) ソレとは別に… >TCHAR szOutput[_MAX_PATH * 5 + 1024]; スタックサイズ、大丈夫ですか? >wmemset(szOutput, 0x00, _countof(szOutput)); が通っているのならば、スタックオーバーフローはしていないのでしょうけど。 # 特に設定を変更していなければ、VCでのリンカーではスタックサイズ1Mのハズです。 # で、上記のローカル変数は1M超えてませんかね?

shotacom
質問者

補足

念のため TCHAR szOutput[_MAX_PATH * 5 + 1024]; ↓ TCHAR szOutput[1024]; に変更しました。 swprintfは、オーバーロードされてるみたいで、VC++でswprintfにオンマウスすると、 size_t型がないswprintfもあるようで、そちらを使っていました。 ですのでエラーも警告もでなかったようです。しかし、 swprintf(szOutput,_countof(szOutput),L"実行しているプログラムのフルパス名%s\r\nドライブ%s\r\nディレクトリ%s\r\nファイル名%s\r\n拡張子%s",szPath, szDrive, szDir, szFileName, szExt); このようにしてもやはりアクセス違反がおきてしまいます。

関連するQ&A

  • システムの特殊なフォルダのパス名の取得を取得しようとしています。

    システムの特殊なフォルダのパス名の取得を取得しようとしています。 VC++2008 Express EditionでSHGetSpecialFolderPathをつかって パスを取ってみようとネット上の例だから拝借して 下記のようなソースを書いてみたのですが、 出てくる結果が、どの場所のパスをとっても「C」しか出てこないのです。 これってなにが原因なのでしょうか? どなたかお教え願えないでしょうか? [ソース] #include<stdio.h> #include<shlobj.h> int main(){ TCHAR buf[_MAX_PATH]; SHGetSpecialFolderPath(NULL, buf, CSIDL_DESKTOPDIRECTORY, FALSE); printf("デスクトップのパスは %s です\n",buf); return 0x00; }

  • ネットワーク初心者です。

    ネットワーク初心者です。 borland C++でプログラム作成しているのですが、windowsクライアントからサーバーに対してソケットを生成して(c言語)、ファイルをhttp通信で送信したいんですが、うまくいきません。とりあえず、ソケット生成とサーバーcgiプログラムを呼び出すことは出来たんですが、それに対してhttpでファイルを送信するには、どうすればいいのでしょうか? 誰か、ご教授願えますか? ちなみに、サーバーcgi呼び出したのは、 sprintf(send_buf, "POST %s http/1.0\r\n\r", path); send(s, send_buf, strlen(send_buf),0); sprintf(send_buf, "Host: %s:%d\r\n", host, port); send(s, send_buf, strlen(send_buf), 0); sprintf(send_buf, "\r\n"); send(s, send_buf, strlen(send_buf), 0); です。

  • どうか、POSTでのファイル転送の仕方を教えてください。

    どうか、POSTでのファイル転送の仕方を教えてください。 borland C++でhttp通信プログラムを書いています。 POSTを使ってhttp通信でファイルをサーバーに転送したいのですが、良く分かりません。 取り合えず、現状としてはwinsockを利用してファイルを転送しようとしました。 (ソース) SOCKET s; [ソケット生成完了] sprintf(send_buf, "POST %s /HTTP1.0\r\n\rHost: %s:%d\r\n", path, host, port); send(s, send_buf, strlen(send_buf), 0); sprinf(send_buf, "\r\n"); send(s, send_buf, strlen(send_buf), 0); ここまでは来たのですが、ここからwhileのfgetsでファイルをバッファにいれてソケットで送信したら、ただのソケット通信になってしまのでここからが分かりません。 この方法であっているのかも、よく分かりません。 http通信でファイルを転送するには、どうすればよいのでしょうか? どなたか、お教え願えませんか?

  • Run-Time Check Failure #3 と表示されてしまうことについて

    初歩的な質問で申し訳ありません。 Visual Studio C++にて、入力された値を基に最短(最小値)を求めていくプログラムを作成しているのですが、 ”Run-Time Check Failure #3 - The variable 'x' is being used   without being defined.” と表示されて、コマンドプロンプトが実行されません。 なぜこうなってしまうのですか? 参考までに下記に作成したソースコードを示します。 初心者ゆえ書き方がしっかりとできておらず、大変わかりにくいソースかとは思いますが、助言をいただければ幸いです。 #include "stdafx.h" #include "stdlib.h" #define MAX_LINE 256 #define MIN_DATA 3 int _tmain(int argc, _TCHAR* argv[]) { char buf[MAX_LINE]; int i,x,y,z,min_data; int data[MIN_DATA] = {x,y,z}; printf("Sからaまでの距離を入力して下しい。\n"); gets(buf); /*キーボードから値を入力*/ x = atoi(buf); printf("a=%dです。\n",x); printf("Sからbまでの距離を入力して下しい。\n"); gets(buf);/*キーボードから値を入力*/ y = atoi(buf); printf("b=%dです。\n",y); printf("Sからcまでの距離を入力して下しい。\n"); gets(buf);/*キーボードから値を入力*/ z = atoi(buf); printf("c=%dです。\n",z); printf("並べ替えると\n"); min_data = data[30];/*入力された値を降順で並べ最小値を表示*/ for (i = 0; i < MIN_DATA; i++) { if (min_data > data[i]) { min_data = data[i]; } } printf("最短は %d\n", min_data); printf("Enterで終了"); return (0); }

  • 動的メモリの確保の仕方がわからなくて困っています

    バージョンリソースの情報を取得しようと以下の関数をつくったのですがバージョンがうまく読み出せません。環境はVC6.0++です。 /*--------------------------------------------------------*/ char *get_version() { #pragma comment (lib, "version.lib") char szFileName[MAX_PATH]; DWORD dwZero = 0, dwVerInfoSize; unsigned char *szBufferBlock; void *szBufferVersion; UINT VersionLen; GetModuleFileName( NULL, szFileName, sizeof( szFileName)); dwVerInfoSize = GetFileVersionInfoSize( szFileName, &dwZero); if (dwVerInfoSize){ szBufferBlock = (unsigned char *)calloc( dwVerInfoSize, sizeof(char)); GetFileVersionInfo( szFileName, dwZero, dwVerInfoSize, szBufferBlock); if(!szBufferBlock){ } VerQueryValue( szBufferBlock, TEXT("\\StringFileInfo\\041104b0\\ProductVersion"), &szBufferVersion, &VersionLen); } free((void *)szBufferBlock); return (char *)szBufferVersion; }/*--------------------------------------------------------*/ unsigned char *szBufferBlock;を unsigned char szBufferBlock[1604];のようにして 静的に確保するとバージョンをちゃんと返すのですが、 上記のようにcallocをやnew演算子を使うとソソソソソソソソソソソソのような文字列しか返さなくなります。 原因がわかりません。教えてください。

  • system関数がうまくいかない

    BCCでコマンドライン引数を持ったDOSのプログラムを作っています。 プログラム内で自身を呼び出すために char path[MAX_PATH]; char str[MAX_PATH]; GetModuleFileName(NULL, path, MAX_PATH); strcpy(str, "\""); strcat(str, path); strcat(str, "\""); system(str); strcat(str, " \"コマンドライン引数\""); system(str); と書いたのですが、下だけうまくいきません。 どこを改善すればうまくいくようになるでしょうか? 分かる方がいらっしゃいましたら回答お願いします。

  • ShellExecute、エクスプローラで選択状態

    お世話になってます。 VC++2010、MFCでファイルリストを生成するプログラムを作っています。 (今回質問した部分以外は正常に動作しています) ファイル生成後、エクスプローラで、生成したリスト(○○.html)を選択状態にしたいです。 しかし、デスクトップ直下に同名のファイル( 例: AlbumList.html )が既にある場合、うまく行きません。 【不具合1】ファイルの生成は意図したディレクトリにされているのに、エクスプローラに「/select」をつけて、開くと、デスクトップ直下の同名のファイル( 例: AlbumList.html )が開かれて(選択されて)しまう   TRACE(_T("◆FileName→%s \r\n" ),FileName);   TRACE(_T("◆savePath→%s \r\n" ),savePath);   //★エクスプローラで開く   ShellExecute( NULL, _T("open"), _T("C:\\WINDOWS\\EXPLORER.EXE"), _T("/select,") + FileName , savePath, SW_SHOWNORMAL ); トレース結果:  ◆FileName→AlbumList.html  ◆savePath→D:\\Visual Studio 2010 - Data\\Projects\\FileListCreator_Shift-JIS(75)\\Debug\\FileListCreator(LIST)\\ エクスプローラに開かれて、選択状態になったファイル  C:\ユーザ\[ユーザ名]\デスクトップ\AlbumList.html 更新されたファイル  D:\Visual Studio 2010 - Data\Projects\FileListCreator_Shift-JIS(75)\Debug\FileListCreator(LIST)\AlbumList.html 【不具合2】デスクトップに ・ FileListCreator.lnk (リンク)(H:\FileListCreator へのリンク) ・ FileListCreator (フォルダ)(デスクトップにおいた FileListCreator.exe が入っているフォルダ)  (C:\Users\[ユーザ名]\Desktop\FileListCreator) があり、FileListCreator.exe から 以下のコードを実行するボタンを押すと、リンクの方が開かれてしまう。 ※リンクフォルダ名、exe名ともに、「FileListCreator」でかつ両方がデスクトップにおかれている場合に問題が起こる。   //http://rararahp.cool.ne.jp/vc/vctips/api.htm   // 実行ファイルのフルパス取得   TCHAR szPath[_MAX_PATH];   GetModuleFileName( NULL, szPath, MAX_PATH);   CString CurDir;   CurDir = CurrentDirFunc(szPath); //szPathからファイル名を取り除くユーザー関数   if (CurDir !=_T("")){     CurDir.Replace(_T("\\"),_T("\\\\"));   }   //★エクスプローラで開く   ShellExecute(NULL, _T("open"), CurDir, NULL, NULL, SW_SHOWNORMAL); リンクファイル名を 「FileListCreator2.lnk」などと違う名前にすると、実行ファイルのディレクトりが正しく開かれる。  →【不具合2】の方は、うまく説明できないので、(1)だけでもお教え下さると嬉しいです。 宜しくお願いします。

  • 指定した文字列を探して・・・

        第1引数の文字列中に第2引数で指定した文字がある場合に、その     文字のあるアドレス(ポインタ)を返す関数doko()作成し、     プログラムを完成させよ。     指定した文字がない場合はNULL(ヌルポインタ)を返すものとする。     配列の[](カギカッコ)を利用しないで作る事     main内は変えないこと いろいろと模索したのですが、strcpyなどは使うのでしょうか? 参考サイトを見たりしたり、ほかの質問などを見たのですが なかなか理解できずに現在にいたってます 以下のコードのdokoは沢山やりすぎたので一番シンプルな間違い方をしています 何かご指摘あればお願いします #include <stdio.h> #define MAX 128 char* doko(char *,char); int main() { char buf[MAX]; char *p = "abcdef12345"; char *r; r = doko(p, 'f'); if (r == NULL) { printf("mojiretsu ni f toiu moji ha arimasen\n"); return 0; } printf("%s (= f12345)\n", r); scanf("%s", buf); r = doko(buf, 'x'); if (r == NULL) { printf("mojiretsu ni x toiu moji ha arimasen\n"); return 0; } printf("%s\n", r); return 0; } char* doko(char *p,char a) { while(*p){ if(*p == a){ return p; } if(*p != a){ return NULL; } ++p; } }

  • プログラムが止まってしまいます

    Visual Studio 2012 c++ でプログラムを動かそうと思っているのですが、デバッグ開始すると画像のようなウィンドウが出て実行途中で止まってしまいます。 呼び出し履歴のint mqoLoadFileのソースを貼ります. int mqoLoadFile( MQO_OBJECT *mqoobj, char *filename, double scale, unsigned char alpha) { FILE *fp; MQO_OBJDATA obj[MAX_OBJECT]; MQO_MATDATA *M = NULL; char buf[SIZE_STR]; // 文字列読み込みバッファ char path_dir[SIZE_STR]; // ディレクトリのパス char path_tex[SIZE_STR]; // テクスチャファイルのパス char path_alp[SIZE_STR]; // アルファテクスチャファイルのパス int n_mat = 0; // マテリアル数 int n_obj = 0; // オブジェクト数 int i; // MaterialとObjectの読み込み fopen_s(&fp,filename,"rb"); if (fp==NULL) return 0; mqoobj->alpha = alpha; memset(obj,0,sizeof(obj)); i = 0; while ( !feof(fp) ) { fgets(buf,SIZE_STR,fp); // Material if (strstr(buf,"Material")) { sscanf_s(buf,"Material %d", &n_mat); M = (MQO_MATDATA*) calloc( n_mat, sizeof(MQO_MATDATA) ); mqoReadMaterial(fp,M); } // Object if (strstr(buf,"Object")) { sscanf_s(buf,"Object %s", obj[i].objname);//ココの実行中に止まる mqoReadObject(fp, &obj[i]); i++; } } n_obj = i; fclose(fp);

  • HTTPクライアントの作成について

    下のc言語で書かれたプログラムソースは、とあるHPにあったものです。受信して表示するだけですが、実際にコンパイルもでき動作も確認しています。仕組みも大体は理解しているつもりです。このプログラムを改造して、リンクのURLの一覧のみ表示させるには、どのように改造すればよいのでしょうか?それとも、根本的に仕組みが異なるのでしょうか?詳しくご指導いただけるとありがたいです。そのHPのURLものせておきます。よろしくお願いします。 URL:http://x68000.q-e-d.net/~68user/net/c-http-1.html ※includeは省略しています。 #define BUF_LEN 256 /*バッファのサイズ */ int main(int argc, char *argv[]){ int s; /*ソケットのためのファイルディスクリプタ */ struct hostent *servhost; /*ホスト名と IP アドレスを扱うための構造体 */ struct sockaddr_in server; /*ソケットを扱うための構造体 */ struct servent *service; /*サービス (http など) を扱うための構造体 */ char send_buf[BUF_LEN]; /* サーバに送るHTTP プロトコル用バッファ */ char host[BUF_LEN] = "localhost"; /*接続するホスト名 */ char path[BUF_LEN] = "/"; /*要求するパス */ unsigned short port = 0; /*接続するポート番号 */ if ( argc > 1 ){ /*URLが指定されていたら */ char host_path[BUF_LEN]; if ( strlen(argv[1]) > BUF_LEN -1 ){ fprintf(stderr, "URL が長すぎます。\n"); return 1; } /*http:// から始まる文字列で */ /*sscanf が成功して */ /*http:// の後に何か文字列が存在するなら */ if ( strstr(argv[1], "http://") && sscanf(argv[1], "http://%s", h ost_path) && strcmp(argv[1], "http://") ){ char *p; p = strchr(host_path, '/'); /* ホストとパスの区切り "/" を調べる */ if ( p != NULL ){ strcpy(path, p);/*"/"以降の文字列を path にコピー */ *p = '\0'; strcpy(host, host_path ); /*"/"より前の文字列を host にコピー */ } else {/*"/"がないなら=http://host という引数なら */ strcpy(host, host_path); /*文字列全体を host にコピー */ } p = strchr(host, ':'); /*ホスト名の部分に ":" が含まれていたら */ if ( p != NULL ){ port = atoi(p+1); /*ポート番号を取得 */ if ( port <= 0 ){ /*数字でない (atoi が失敗)か、0だったら */ port = 80; /*ポート番号は 80 に決め打ち */ } *p = '\0'; } } else { fprintf(stderr, "URLはhttp://host/path の形式で指定してください。\n"); return 1; } } printf("http://%s%s を取得します。\n\n",host, path); /* ホストの情報(IPアドレスなど)を取得 */ servhost = gethostbyname(host); if ( servhost == NULL ){ fprintf(stderr, "[%s] から IPアドレスへの変換に失敗しました。\n", host); return 0; } bzero(&server, sizeof(server));  /* 構造体をゼロクリア */ server.sin_family = AF_INET; /* IPアドレスを示す構造体をコピー */ bcopy(servhost->h_addr, &server.sin_add r,servhost->h_length); if ( port != 0 ){/* 引数でポート番号が指定されていたら */ server.sin_port = htons(port); } else {/* そうでないなら getservbyname でポート番号を取得 */ service = getservbyname("http", "tcp"); if ( service != NULL ){  /* 成功したらポート番号をコピー */ server.sin_port = service->s_port; } else { /* 失敗したら 80 番に決め打ち */ server.sin_port = htons(80); } } /* ソケット生成 */ if ( ( s = socket(AF_INET, SOCK_STREAM, 0) ) < 0 ){ fprintf(stderr, "ソケットの生成に失敗しました。\n"); return 1; } /* サーバに接続 */ if ( connect(s, (struct sockaddr *)&ser ver, sizeof(server)) == -1 ){ fprintf(stderr, "connectに失敗しました。\n"); return 1; } /* HTTP プロトコル生成 & サーバに送信 */ sprintf(send_buf, "GET %s HTTP/1.0\r\n" , path); write(s, send_buf, strlen(send_buf)); sprintf(send_buf, "Host: %s:%d\r\n", ho st, port); write(s, send_buf, strlen(send_buf)); sprintf(send_buf, "\r\n"); write(s, send_buf, strlen(send_buf)); /* あとは受信して、表示するだけ */ while (1){ char buf[BUF_LEN]; int read_size; read_size = read(s, buf, BUF_LEN); if ( read_size > 0 ){ write(1, buf, read_size); } else { break; } } /* 後始末 */ close(s); return 0; }

専門家に質問してみよう