• 締切済み

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

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);

みんなの回答

  • chie65535
  • ベストアンサー率43% (8519/19367)
回答No.3

因みに。 sscanfを使うと「sscanf_sに直せ」とコンパイラに怒られる ↓ 単純にsscanfをsscanf_sに修正するだけで関数仕様を確認しない ↓ 訳判らんエラーで止まったり、マトモに読み込まないで文字が切れる ↓ 動かなくてドツボる と言うのは、C++のプログラマなら、必ず1度は通る道です。

  • chie65535
  • ベストアンサー率43% (8519/19367)
回答No.2

sscanf_sの「%s」と「%c」には、バッファのポインタに続いて、バッファサイズを指定しなければならない。 >sscanf_s(buf,"Material %d", &n_mat); はOKだが >sscanf_s(buf,"Object %s", obj[i].objname);//ココの実行中に止まる は「バッファサイズの指定がない」ので、サイズは「メモリ上のゴミ」つまりは「不定な値」が指定されたことになる。 sscanf_s(buf,"Object %s", obj[i].objname,_countof(obj[i].objname)); のように「バッファのポインタ」に続いて「バッファのサイズ」を「要素数」で指定しなければならない。 一部「バイト数」を返す「sizeof()マクロ」で説明しているサイトがあるが、ワイド文字版のswscanf_s()を使った時は「バイト数を指定したらバグる」ので、sizeof()を使うのは間違い。_countof()を使用する事。

  • 8shi8
  • ベストアンサー率32% (90/274)
回答No.1

エラーの画面が拡大できないのでエラー内容がわかりません ざっとコードを見た結果、メモリーを壊しそうなコードが存在します 変数bufをSIZE_STRで確保し、fgetsでSIZE_STR読み込みしています 読み込んだ1行のサイズがSIZE_STRを超えた場合SIZE_STR分読み込んだあとに0x00を追加します つまりfgetsでSIZE_STRを読み込むのであれば、bufのサイズはSIZE_STR+1を指定する必要があります

関連するQ&A

  • プログラム

    { FILE *fp; char *str,buf[1000];   char subbuf[100],*s1; char buf2[100],*s2;   char buf3[100],*s3; char buf4[100],*s4; static double bx=0; static double by=0; if ((fp = fopen("test.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str!='\0' && *str=='G'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s2=buf2; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0'&&(isdigit(*str) || *str=='-' || *str=='.')) *s2++=*str++; *s2='\0'; } if(*str!='\0' && *str=='X'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s3=buf3; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) *s3++=*str++; *s3='\0'; } if(*str!='\0' && *str=='Y'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s4=buf4; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) |*str=='||*str=='.')) *s4++=*str++; *s4='\0'; } CDC *v; v=GetDC(); if((int)atof(buf2)==92){ MoveTo((int)atof(buf3),(int)atof(buf4)); bx=(int)atof(buf3); by=(int)atof(buf4); ReleaseDC(v); } else if((int)atof(buf2)==01){ MoveTo((int)bx,(int)by); LineTo((int)atof(buf3),(int)atof(buf4)); bx=(int)atof(buf3); by=(int)atof(buf4); ReleaseDC(v); } else str++; } } fclose(fp); return 0; } という風なプログラムになっているのですが 今現在 G01X30Y30 G01X30Y120というファイルをこのプログラムにて実行すると (0,0)→(30,30)→(30,120)というような直線が引かれます。 しかしこれを G01X30Y30 Y120 とかかれたときも同様の結果がでるようにしたいです。 つまり最初のG○○が省略されているときは前回のGの値を X○○が省略されているときは前回のXの値を使うように 変更したいのですがどのように変更すればいいのかがわかりません。 教えてください。

  • プログラム

    { FILE *fp; char *str,buf[1000]; char xbuf[100],*xstr;   char ybuf[100],*ystr; static double bx=0; static double by=0; if ((fp = fopen("kadai.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str!='\0' && *str=='X'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) xstr=xbuf; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) *xstr++=*str++; *xstr='\0'; } if(*str!='\0' && *str=='Y'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) ystr=ybuf; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) |*str=='||*str=='.')) *ystr++=*str++; *ystr='\0'; } else str++; } pDC->MoveTo((int)bx,(int)by); pDC->LineTo((int)atof(xbuf),(int)atof(ybuf)); bx=(int)atof(xbuf); by=(int)atof(ybuf); } } fclose(fp); return 0; } とテキストファイルを読み込みその中のXとYに付属する値を 取り出し図形を書くというプログラムなのですが X100Y100 X200Y100というファイルなら (0,0)→(100,100)→(200,100)という2つの直線が描かれます。 実行の結果正常に動きました。 str=buf; の部分ではbufの先頭要素のアドレスをstrに設定している のはわかりました。 しかしxstr=xbufの所ではわからないことがあります。 bufでfpから読み込んだ文字列1行が入っているのはわかります。 しかしxbufにはまだ何も入ってないはずなのに xstr=xbufの所でxbufにはxの値がしっかり入っていました。 これはどうしてでしょうか xbufとかybufとかいらないような気もするのですが もしそうならばどのように書き直せばいいのでしょうか? この2点について教えてください。

  • プログラム

    以前ファイルからXとYの値だけ取り出し図形を作る質問をした者ですが void Ctest::OnOK() { FILE *fp; char *str,buf[1000];     char buf3[100],*s3; char buf4[100],*s4; if ((fp = fopen("test.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str!='\0' && *str=='X'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s3=buf3; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) *s3++=*str++; *s3='\0'; } if(*str!='\0' && *str=='Y'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s4=buf4; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) |*str=='||*str=='.')) *s4++=*str++; *s4='\0'; CDC *v; GetDC(); MoveTo(0,0); LineTo(atof(buf3),atof(buf4)); ReleaseDC(v); } else str++; } } fclose(fp); return 0; } でコンパイルはできるのですが直線の作図がされません。 どこが間違ってるのでしょうか。VC+6.0のMFC使ってます

  • 関数化

    #include <ctype.h> #include <string.h> #include <stdlib.h> void swap(char p[], char q[]); char *get(char *str, char buf[], int line, int field); typedef struct { int number; char *class_type; char* name; char *subject; } my; my *data; int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char *bufG; int line2 = 0; if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf, 1000, fp) != NULL){ line2++; } fclose(fp); printf("%d\n", line2); if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } data = (my *)malloc(sizeof(my) * line2); while(fgets(buf,1000,fp) != NULL){ str = buf; while(*str != '\0'){ bufG = get(str, buf, line, field); switch(field){ case 0: data[line].number = atoi(bufG); break; case 1: data[line].class_type = (char *)malloc(strlen(bufG) +1); strcpy(data[line].class_type, bufG); break; case 2: data[line].name = (char *)malloc(strlen(bufG) + 1); strcpy(data[line].name, bufG); break; case 3: data[line].subject =(char *)malloc(strlen(bufG) + 1); strcpy(data[line].subject, bufG); break; } str++; field++; } line++; field = 0; } fclose(fp);     for(int m = 1; m < line; m++){ printf("%d\n", data[m].number); printf("%s\n", data[m].class_type); printf("%s\n", data[m].name); printf("%s\n", data[m].subject);     } return 0; } char *get(char *str, char buf[], int line, int field) { char bufG[1111]; int i; for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; return bufG; } 前回の質問 http://okwave.jp/qa5094929.html で提示していただいたサンプルの関数化をはかりましたが うまくいきません。これを実行すると1しか表示されません。 原因はおそらくポインタだと思いますがどうすればいいのか わかりません。教えて下さい。bufを引数にする意味ないのでは という意見は今の所はとりあえずなしで fieldの値によってbufGが色々とってくる。 例えば1,A,山田,数学の場合 field = 0のときbufGは1 filed=1のときbufGはA field=2のときbufGは山田 filed=3のときbufGは数学という ような値が返ってくるようにしたいです。

  • メモリ2(ポインタ編)

    #include "stdafx.h" #include <ctype.h> #include <string.h> #include <stdlib.h> int check(int a[100], int n); typedef struct { char *number; char *class_type; char *name; char *subject; } my; int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char bufG[1111]; int i, len; my *o; if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf,1000,fp) !=NULL){ str=buf; len = strlen(buf); o = (my *) calloc(len + 1, sizeof(my *)); while(*str != '\0'){ if(*str != ','){ for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; switch(field){ case 0: o[line].number = bufG; break; case 1: o[line].class_type = bufG; break; case 2: o]line].name = bufG; break; case 3: o[line].subject = bufG; } field++; } else{ str++; } } line++; field = 0; } fclose(fp); return 0; } 固定なのがいけないといわれたのでこのように 変更しました。もちろん上手く動かないわけですが 原因を教えて下さい。 ちなみにエラーはo[0].numberが国語とかになってたり ちゃんとアクセスができません。

  • CArray

    #include <ctype.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE -1 char* get(char **p_str); char *get_line(char buf[]); int comp_rtn(const void *p1, const void *p2); typedef struct { int number; char class_type[10]; char name[15]; char subject[10]; int ten; } my; my *data; void myswap(my *p, my *q); int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char *bufFormat; char *bufG; int line2 = 0; if((fp=fopen("jjj.txt","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf, 1000, fp) != NULL){ line2++; } fclose(fp); if((fp=fopen("jjj.txt","r"))==NULL){   printf("ファイルが開けません"); } data = (my *)malloc(sizeof(my) * line2); while(fgets(buf,1000,fp) != NULL){ bufFormat = get_line(buf); str = bufFormat; while(*str != '\0'){ bufG = get(&str); switch(field){      case 0: data[line].number = atoi(bufG); break case 1: strcpy(data[line].class_type, bufG); break; case 2: strcpy(data[line].name, bufG); break; case 3: strcpy(data[line].subject, bufG); break; case 4: data[line].ten = atoi(bufG); break; } str++; field++; } line++; field = 0; } fclose(fp); qsort(data,line,sizeof(my),comp_rtn); for(int m = 0; m < line; m++){ printf("%d\n", data[m].number); printf("%s\n", data[m].class_type); printf("%s\n", data[m].name); printf("%s\n", data[m].subject); printf("%d\n", data[m].ten); printf("\n"); } free(data); return 0; } void myswap(my *p, my *q) { my temp; temp = *p; *p = *q; *q = temp; } char *get(char **p_str) { int i; char *str; str = *p_str; static char bufG[1000]; for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else if(*str == '\\'){ str++; if(*str == 'c'){ bufG[i] = ','; } else if(*str == '"'){ bufG[i] = '"'; } } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; *p_str = str; return bufG; } char *get_line(char buf[]) { int in_quotation = FALSE, i = 0; char* str = buf; static char bufG[1000]; while(*str != '\0'){ if(*str=='"'){ if(in_quotation == TRUE){ str++; if(*str == '"'){ bufG[i] = '\\'; i++; bufG[i] = '"'; i++; } else{ in_quotation = FALSE; bufG[i] = *str; i++; } } else{ in_quotation = TRUE; } } else{ switch(*str){ case '\n': if(in_quotation == TRUE){ bufG[i] = '\\'; i++; bufG[i] = 'n'; i++; } else{ bufG[i] = *str; i++; } break; case ',': if(in_quotation == TRUE){ bufG[i] = '\\'; i++; bufG[i] = 'c'; i++; } else{ bufG[i] = *str; i++; } break; default: bufG[i] = *str; i++; } } str++; } bufG[i] = '\0'; return bufG; } 以前上記のソースになるプログラムの質問をいくつかしました。 これはCで組んでますがC++で組みなおすに当たり 今mallocを使っていますがCArrayを使用するように薦められました どういう感じになるのかさっぱりわかりません。

  • csvファイルの読み込みで失敗します

    以下のようなソースでカンマ区切りのテキストファイルであるcsvファイルの行数、列数、要素数を取得するプログラムを作っているのですが、終わりのメモリ解放であるdelete []strのところでプログラムが落ちてしまいます。範囲外のメモリにアクセスしてしまっているのかと思いますが、ミスを特定できないので、教えてください。 読み込むcsvファイルには以下のような小数の値が入っています。 0.23960810421811729043, 11.753428210139766463, …(省略) , 3.8736893050771881164 int main( int argc, char **argv ) { int csvRowNum, csvColNum, csvElemNum; GetCSVDataNum ( "C:\\Data.csv", csvRowNum, csvColNum, csvElemNum ); return 0; } // csvファイルから行数、列数、要素数を取得する int GetCSVDataNum ( char *csv_name, int &rowNum, int &colNum, int &elemNum ) { FILE *fp; fp = fopen( csv_name, "r" ); if( fp == NULL ){ printf( "ファイルオープンエラー\n" ); exit(1); } // ファイルサイズの取得 int fsize; fseek( fp, 0L, SEEK_END ); fsize = ftell( fp ); // ファイルシーク位置を先頭に戻す fseek( fp, 0L, SEEK_SET ); // ファイルサイズに合わせて文字列領域確保 char *str; str = new char[fsize]; char buf[10000]; // ファイルから1行ずつテキストデータを読み込み、 // 連結してbufに格納する str[0] = '\0'; while ( fgets( buf, sizeof(buf), fp ) != NULL ) { strncat( str, buf, strlen(buf) ); } int countSep = 0; // '(カンマ)の数のカウント int cols = 0; // 各行の列数をカウント int countNL = 0; // 改行の数をカウント // 要素数、行数、列数の取得 for ( int i = 0; i < (int)strlen(str); i++ ) { switch( str[i]){ case ',': countSep++; cols++; break; case '\n': countNL++; cols++; // 各行で列数が異なるときは、最も大きい列数とする colNum = (colNum > cols ) ? colNum: cols; cols = 0; break; default: break; } } rowNum = countNL; elemNum = countSep + countNL; // strの解放で落ちる delete[] str; fclose( fp ); return 0; }

  • 一番大きい奇数を表示する

    scanf関数を使って数字を10回入力して一番大きなものを表示させるプログラムをつくったのですが、 さらに一番大きな奇数を表示するにはどうすればいいのでしょうか? 偶数=割り切れる 奇数=割り切れない というところまでは分かるのですが、以下のプログラムに奇数を判別するソースを追加するのにはどうすればいいのでしょうか。 #include <stdio.h> int main(void) { char str[1024]; char buf[10]; int i; int w; printf("文字列を10回入力して下さい:\n"); memset(str, 0, sizeof(str)); for (i = 0; i < 10; i++) { memset(buf, 0, sizeof(buf)); printf("input>\n"); scanf("%s", buf); } for (i = 0; i < 10; i++) { if ((buf[i] & 1) == 1) /* 奇数であるか */ { if (strcmp(buf, str) > 0) { strcpy(str, buf); } } } printf("output>\n%s\n" , str); getchar(); }

  • このプログラムは

    どこかおかしいですか? int main(void){ FILE *str; char buf[1000]; if((fp=fopen("ファイル名","r"))=NULL){ printf("ファイルが開けません"); return EXIT_SUCCESS; } while(fgets(buf,1000,fp) !=NULL){ str=buf; printf("%s",buf); } return EXIT_SUCCESS; } で実行すると前半4割程度が表示されません。 何故だかわかる人いませんか? 使用言語:C言語 環境:visualC++6.0 のコンソールアプリケーション。

  • switchとメモリ取得位置

    #include <stdlib.h> #include <string.h> #include <ctype.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE -1 char* get(char **p_str); char *get_line(char buf[]); int comp_rtn(const void *p1, const void *p2); typedef struct { int number; char class_type[10]; char name[15]; char subject[10]; int ten; } my; my *data; void myswap(my *p, my *q); int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char *bufFormat; char *bufG; bufG = (char *)malloc(1000); if(bufG == NULL){ printf("メモリ不足"); free(bufG); } int line2 = 0; if((fp=fopen("jjj.txt","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf, 1000, fp) != NULL){ line2++; } fclose(fp); if((fp=fopen("jjj.txt","r"))==NULL){   printf("ファイルが開けません"); } data = (my *)malloc(sizeof(my) * line2); if(data == NULL){ printf("メモリ不足"); free(data); } while(fgets(buf,1000,fp) != NULL){ bufFormat =(char *)malloc(strlen(buf) + 1); if(bufFormat == NULL){ printf("メモリ不足"); free(data); } bufFormat = get_line(buf); str = bufFormat; while(*str != '\0'){ bufG = get(&str); switch(field){      case 0: data[line].number = atoi(bufG); break case 1: strcpy(data[line].class_type, bufG); break; case 2: strcpy(data[line].name, bufG); break; case 3: strcpy(data[line].subject, bufG); break; case 4: data[line].ten = atoi(bufG); break; } str++; field++; } line++; field = 0; } fclose(fp); qsort(data,line,sizeof(my),comp_rtn); for(int m = 0; m < line; m++){ printf("%d\n", data[m].number); printf("%s\n", data[m].class_type); printf("%s\n", data[m].name); printf("%s\n", data[m].subject); printf("%d\n", data[m].ten); printf("\n"); } free(data); return 0; } void myswap(my *p, my *q) { my temp; temp = *p; *p = *q; *q = temp; } char *get(char **p_str) { int i; char *str; str = *p_str; static char bufG[1000]; for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else if(*str == '\\'){ str++; if(*str == 'c'){ bufG[i] = ','; } else if(*str == '"'){ bufG[i] = '"'; } } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; *p_str = str; return bufG; } char *get_line(char buf[]) { int in_quotation = FALSE, i = 0; char* str = buf; static char bufG[1000]; while(*str != '\0'){ if(*str=='"'){ if(in_quotation == TRUE){ str++; if(*str == '"'){ bufG[i] = '\\'; i++; bufG[i] = '"'; i++; } else{ in_quotation = FALSE; bufG[i] = *str; i++; } } else{ in_quotation = TRUE; } } else{ switch(*str){ case '\n': if(in_quotation == TRUE){ bufG[i] = '\\'; i++; bufG[i] = 'n'; i++; } else{ bufG[i] = *str; i++; } break; case ',': if(in_quotation == TRUE){ bufG[i] = '\\'; i++; bufG[i] = 'c'; i++; } else{ bufG[i] = *str; i++; } break; default: bufG[i] = *str; i++; } } str++; } bufG[i] = '\0'; return bufG; } 構造体メンバをポインタで宣言する方法はもうできていて 配列の方も組んでいるのですが 比較関数など所々省いてますがこのプログラムに対し以下のことをいわれました 1,switch文のfieldの値を数字じゃなく分かりやすいのに変えよ 2,mainのすぐしたの bufG = (char * )malloc(1000)が なかなか使用されないのにここでメモリを取るのはおかしい 3,これを使うまでの間にエラーが発生したときのfreeがない と言われました。 1ですが確かCではswitch文のcase式は整数型定数でなければならない とあるので無理な気もするのですが、方法ありますか? 2に関してはよくわかりません。効率がよくないのでしょうか? どの場所がいいのでしょうか 3に関してはどういうことなのかもわかりません。 この3点について教えて下さい。

専門家に質問してみよう