vectorを使用したプログラムのエラーについて

このQ&Aのポイント
  • C++のvectorを使用したプログラムでエラーが発生しています。エラーメッセージは「integer overflow」と表示されており、vector内部の問題と思われます。アドバイスをお願いします。
  • C++のvectorを使ったプログラムでエラーが発生しており、ブレークポイントが発生して止まってしまいます。エラーメッセージは「integer overflow」と表示されています。どうすればエラーを解消することができるのでしょうか?
  • C++のvectorを使用したプログラムで、文字を一文字ずつ作成して格納していく過程で「integer overflow」というエラーが発生してしまいます。どうすればこのエラーを解消することができるのでしょうか?
回答を見る
  • ベストアンサー

vectorのついて

昨日、この質問コーナーでDirectXとC++を使って、文字を出力すること について質問させていただきました。的確なアドバイスにより、昨日の 問題は解決したのですが、新たな問題が発生しました。 ちょっと汚いプログラムですが、 for(int i=0; i< strlen(Text); i++) { if(IsKanji1st(Text[i])){ NovelChara* Chara=new NovelChara(); Chara->CreateChara(&Text[i], size, size, FontName); CharaList.push_back(Chara); i++; }else{ NovelChara* Chara= new NovelChara(); Chara->CreateChara(&Text[i],size,size, FontName); CharaList.push_back(Chara); } } のプログラムなんですが、汚いプログラムなんで説明を加えますと、 まず、文字を一文字ずつ作成して格納していくプログラムなのですが、 NovelCharaクラスは一文字のテクスチャ情報を格納するクラス。 それを作って、CreateCharaメソッドを使ってAPIを利用して一文字 の文字画像を作成。それを、CharaListというvectorコンテナに格納 するプログラムです。vector<NovelChara* > CharaList という感じです。これを使い、文章文字を作成していたのですが、 マップ間を移動するたびにマップ内にいるキャラクターの会話文の生成 と前のマップで作った会話文の破棄を繰り返していたのですが、3往復 マップ間を移動したところで、エラーがでました。 デバッグで確認してみると、vector<NovelChara*> に文字を格納している途中で、 for integer overflow if (_Count <= 0) _Count = 0; else if (((_SIZT)(-1) / _Count) < sizeof (_Ty)) _THROW_NCEE(std::bad_alloc, NULL); // allocate storage for _Count elements of type _Ty return ((_Ty _FARQ *)::operator new(_Count * sizeof (_Ty))); } のreturn のところで、ブレークポイントが発生しましたとなって、 とまってしまいます。vector内部は全くわからないので、どなたか このエラーが何が原因で発生しているものなのか知っている方がいらっしゃればアドバイスをお願いしたいのですが

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

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

CharaListを使い終わって開放している部分を確認して下さい。 何もしないで「いきなし、CharaListをdelete」したりすると、確実にメモリリークします。 確実に言える事は1つだけ。それは「newが実行される回数と、deleteが実行される回数は、同じでなければならない」と言う事。 この「回数」には「コピーコンストラクタによる暗黙的なnew」や「auto変数の破棄による暗黙的なdelete」も含まれます。 質問文にあるforループで、auto変数として宣言されている NovelChara* Chara=new NovelChara(); でnewした「クラスの実体」について「誰がどこでdeleteしてくれているのか」を良く考えて下さい。 少なくとも、CharaListをdeleteする前に、以下の処理が必要です。 1. CharaList.push_back(Chara); でプッシュされた回数分、 NovelChara* Chara=new NovelChara(); でnewしたCharaをdeleteする処理。 2. Chara->CreateChara() の中で確保された、すべてのオブジェクトを開放する処理(newした物、画像データを格納しているメモリや、画像ハンドラなど) 以下、蛇足。 for(int i=0; i< strlen(Text); i++) { if(IsKanji1st(Text[i])){ NovelChara* Chara=new NovelChara(); Chara->CreateChara(&Text[i], size, size, FontName); CharaList.push_back(Chara); i++; }else{ NovelChara* Chara= new NovelChara(); Chara->CreateChara(&Text[i],size,size, FontName); CharaList.push_back(Chara); } } は無駄。 2バイト文字と1バイト文字の処理は「やる事は一緒」で「やった後にiを2バイト分進めるか、1バイト分進めるかが違うだけ」なので、以下のようにすれば良い。 for(int i=0; i< strlen(Text); i++) { NovelChara* Chara=new NovelChara(); Chara->CreateChara(&Text[i], size, size, FontName); CharaList.push_back(Chara); if(IsKanji1st(Text[i])) i++; } 更に言えば、ループで毎回strlen()なんか呼んだら遅いし、ループ内で毎回Text[i]のアドレスを求めるのも無駄だし、Text[i]の中身を取り出す為に、もう一度Text[i]のアドレスを求め直すのも無駄。 こういう時は以下のように「ポインタを有効活用」しよう。 for(char *p = Text; *p; p++) { NovelChara* Chara=new NovelChara(); Chara->CreateChara(p, size, size, FontName); CharaList.push_back(Chara); if(IsKanji1st(*p)) p++; } それと「1文字づつ画像を作る事」そのものが無駄。 API関数には「指定のフォント、指定のサイズで、指定の文字列を描画するには、何×何ピクセルの画像領域が必要かを求める関数」や「指定のフォント、指定のサイズで、指定した文字を画像領域に描画する関数」がある。 それを使えば「1枚の画像に、1行分の文字列が描画された物」を作る事も出来るし、工夫すれば「1枚の画像に、複数行の文字列が描画された物」も作れる。 「1文字づつ、バラバラに1つの画像(テクスチャ)を作る」のはかなり無駄、と言うか、リソースを食いまくるので、何とかした方が…。

kaijinu-un
質問者

お礼

非常に参考になりました。 本当にありがとうございます。まずは、メモリーリークの発見を最優先 したいと思いますが、もう一度文字描画クラスを考え直してみます。

その他の回答 (3)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

残念ながらコードの断片しか見えないので, 「確実に解放してるね」とは素直に納得できなかったりします. そのコード片を実行しているのは確実でしょうか? NovelBoxChara と NovelChara の関係は? などなど, 「実は見えないところに問題があるのではないだろうか」と考えられるんですね.

kaijinu-un
質問者

お礼

NovelCharaは一文字のテクスチャ画像に関するクラスで 開放が必要なものはLPDIRECT3DTEXTURE9 Textureのみで、 デストラクタでSAFE_RELEASE(Texture); と開放しております。 そして、NovelBoxCharaクラスは文字列にして出力管理するクラスです。 ここには vector<NovelChara* > CharaListとして定義してあり このクラスで開放が必要なのはこの部分のみで、 デストラクタで、 vector<NovelChara*>::iterator it; for(it=CharaList.begin(); it!=CharaList.end(); it++) {SAFE_DELETE(*it);} CharaList.clear();で開放しております。 さらにこのNovelBoxCharaクラスをConversationクラスというが 使っております。 このクラスはmap<string, NovelBoxChara*> Conv; というmapを持っております。このクラスは他にも解放するもの があるのですが、引っかかるのはこれのみかな。 このクラスもデストラクタで map<string, NovelBoxChara*>::iterator it; for(it= Conv.begin(); it!=Conv.end(); it++){ SAFE_DELETE(it->second); } Conv.clear(); とかいほうしております。 このConversationクラスを使ってキャラクタの固有の会話文を 制御していたのですが…。ちょっと使い物にならないので、 もう一度考え直してみます。

kaijinu-un
質問者

補足

お騒がせしました。無事解決いたしました。 理由は単純で、デバッグしたときに _CrtSetBreakAlloc(567); をコメントにし忘れて、強制的にブレークポイントが 発生するという過ちでした。非常に情けない限りです。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

うん, 私もメモリーリークかなって気がします. std::vector にポインタを入れた場合, デストラクタで「中のポインタが指しているオブジェクトも delete してくれる」というわけではないです.

kaijinu-un
質問者

お礼

う~ん、実は僕もメモリーリークしかないと思っているのです。 なぜなら、例えばマップ間で生成する文字を10文字とした場合には 10往復目ぐらいでシステムダウンするのですが、 変更して生成文字を25に変えると3往復目辺りでシステムダウン します。といううことは、メモリーリークによりヒープが圧迫 されているということになると僕も考えてはいて、ずっと調べて いるのです。 でも、開放は、 map<string,NovelBoxChara*>::iterator it; for(it= LetterBox.begin(); it!=LetterBox.end();it++){ SAFE_DELETE( it->second); } LetterBox.clear(); という風にしっかりしていますし、 NovelBoxCharaクラスの解放も見る限りできていて、 デバッグで、 #ifndef _DENUG_H_ #define _DEBUG_H_ #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #ifdef _DEBUG #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) #endif #endif を使っても開放漏れに引っかからないとはどういうことか 行き詰っています。メモリーリークの見つけ方でいい方法はないでしょうか。

  • oldman50
  • ベストアンサー率29% (8/27)
回答No.1

メモリーリークじゃないのでしょうか?

kaijinu-un
質問者

お礼

やはり。ショック。 でも、三日探し続けて三千里‥。 面白いこともいえなくなって来ました。

関連するQ&A

  • vectorを使っていたいのですが上手くいきません

    文字列(A)から特定の文字列(B)を抽出しながらvectorにどんどん入れていくプログラムを作成しています。(文字列(B)の位置や長さはわかっているとします。) そこで、文字列(A)から、文字列(B)に相当するアドレスをvectorにどんどん入れているのですが、先pushした値が後からpushした値と全て同じ値になってしまいます。 これは、アドレス渡しが原因と分かってはいるのですが、どう書けば上手くいくかわかりません。 そこでご教授頂きたいと思っています。 自分が書いたプログラムは以下になります。 #include <string.h> #include <stdio.h> #include <stdlib.h> #include <vector> using namespace std; void main(){ char* stringA; vector<char*> result; char temp[16];//文字列Bの大きさ for(int i=0;i<file.size();i++){ strncpy(temp,&buffer[i],16); result.push_back(*temp); //次の文字列Bの位置までインデックスを移動//// while(buffer[i]!=0x0A){ i++; } i++; } }

  • Vectorの中のVectorについて

    現在Vectorを使ってプログラムを作っています。 その過程でVettorの中に違うVectorを追加していき、追加されたVectorのsize()を出したいのですが、どのように記述すればいいのかがいまいちわかりません。 というより、そもそもそういうことは可能なのでしょうか? 概要としては --------------------------------------------------------- String[] s ={"a","b","c","d","e","f","g","h","i","j"}; Vector v = new Vector(); Vector x = new Vector(); for (int i=0; i<=9; i++) { v.add(i, s[i]); } x.add(v); のように追加されたVectorの中のVetorの大きさ、つまりこの例なら結果としてVector vの中の要素の数10を出したいのです。 size()を使うのだとは思うのですが・・・・・・・・・。 どうすればVectorの中のVectorの要素数を返すことが出来るのでしょうか? ご教授していただければ幸いです。

    • ベストアンサー
    • Java
  • Vectorでヒープエラーが出る

    下記のプログラムで、2回目のループを抜けたところでヒープエラーが 出てしまいます。 2回目のループ時にv[0]とv[1]の中のbuffが同じポインタを指してしまうことが原因のようですが、なぜ同じポインタを指してしまうのかがわかりません。 どうしたらこの問題が解決するのでしょうか? 以上、よろしくお願いします。 #include "CBuff.h" main(){ vector<CBuff> v; char *tmpstr; for (int i = 0; i < 3; i++){ if (i == 0){ tmpstr = new char[5]; memcpy(tmpstr, "aaaa", 5); }else if(i == 1){ tmpstr = new char[6]; memcpy(tmpstr, "bbbbb", 6); }else { tmpstr = new char[7]; memcpy(tmpstr, "cccccc", 7); } CBuff cb; cb.setBuff(tmpstr, strlen(tmpstr) + 1); v.push_back(cb); delete [] tmpstr; } } 【CBuff.h】 #pragma once class CBuff{ char *buff; public: CBuff(); ~CBuff(); void setBuff(char*, size_t); }; CBuff::CBuff(){ buff = NULL; } CBuff::~CBuff(){ if (buff != NULL){ delete [] buff; buff = NULL; } } void CBuff::setBuff(char *input, size_t size){ buff = new char[size]; memcpy(buff, input, size); }

  • vector間における効率的な値の比較

    2つのベクターに入ったdoubleの網羅的な比較を行う関数をC++で書こうとしています。 (VC++ 2008) doubleのベクター vctr_1 , vctr_2 があるとします。 vctr_1 には (100.0, 200.5 , 300.1 , 400.0 ) vctr_2 には(50.0 , 70.2, 100.1, 220.0 , 300.0 ) というdouble の値が入っていて vctr_1の値のうち、vctr_2に近い値(誤差0.2以内)が見つかるものを.新しいベクターとして返すという処理を考えています。 この場合 100 : 100.1 と300.1: 300.0 が 誤差 0.2 未満で近い値といえ、100 と300.1が格納されたベクターを返す、という処理です。 私の考えた方法はベクターaの各要素に対してベクターbの各要素をループで比較する、というものでした。 以下コード ---------------------------- //比較を行う関数。ベクター1、2 要素の比較をし誤差内の数値をベクター1からとりだし、別のベクターとして返す。 vector<double> compare_doubles_with_tol(vector<double> v1,vector<double> v2 , double tol ){ //似た値を格納するベクター vector<double> v_match; //ベクター1に関してループ vector<double>::iterator it1 = v1.begin(); while( it1 != v1.end() ){ //ベクター2に関してループ vector<double>::iterator it2 = v2.begin(); while( it2 != v2.end() ){ //誤差内の値を見つける if( fabs(*it1 - *it2) < tol ){ v_match.push_back(*it1); } ++it2; } ++it1; } return v_match; } int main() { //ベクター1 std::vector<double> vctr_1; vctr_1.push_back(100.0); vctr_1.push_back(200.5); vctr_1.push_back(300.1); vctr_1.push_back(400.0); //ベクター2 std::vector<double> vctr_2; vctr_2.push_back(50.0); vctr_2.push_back(70.2); vctr_2.push_back(100.1); vctr_2.push_back(220.0); vctr_2.push_back(300.0); //誤差0.2内で似た値があるものを新たなベクターとして得る。 vector<double> matched = compare_doubles_with_tol(vctr_1,vctr_2,0.2); for (int i = 0 ; i < matched.size() ; ++i){ cout << matched[i]<<endl; } return 0; } ------------------------- このコードで望んだ結果は得られますがループの繰り返しを行っていて処理が遅くなってしまいます。実際の仕事ではベクターの要素数が100前後のものを非常に数多く処理しなければならず、このままでは処理時間が膨大なものになってしまいそうです。 このような場合どのような処理、コードを作成すれば処理速度の向上が望めるでしょうか。

  • n × n の二次元配列の各要素に vector を突っ込みたいと思っ

    n × n の二次元配列の各要素に vector を突っ込みたいと思っています。 ちょうど三次元グラフで n × n の地表に可変な高さの草が生えてるようなのを想像していただければやりたいことが分かっていただけるかと。 で、このようにしてまずは確保しました。 int i, n = 2; vector<int> ***vecMatrix; vecMatrix = new vector<int>**[ n ]; for (i = 0 ; i < n ; i++) vecMatrix[ i ] = new vector<int>*[ n ]; ここまでは問題ないのですが、次に vecMatrix[ i ][ j ] に対して要素を格納しようとして、 vecMatrix[ 0 ][ 0 ]->push_back( 1 ); とすると segmentation fault で落ちます。 ううーん、なぜでしょう。

  • Vectorクラスの使い方

    いつもお世話になっております。 Vector vector = new Vector(); String array[] = new String[11]; vector.addElement(array) for( int i = 0; i1 < vector.size(); i++) { String str = (String)vector.get(i); System.out.println(str); } 11の配列にデータ(String)を入力し(ここでは省略)、11すべてをVectorへいれ、String型で取り出したいのですがエラーになります。 System.out.println(vector1.get(i));だと文字化けします。 アドバイスお願いします。そういったことを書いてあるサイト等ご存知でしたらお願いします。

    • ベストアンサー
    • Java
  • 「シンボルを見つけれません」というエラーへの対処法

    下記のコードの If(type.compareTo("名詞") == 0); で「シンボルを見つけれません」「シンボル:メソッドif(boolean)」というエラーが出てしまいます。 なぜ、他のif文ではエラーが出ないのにこの行ではエラーが出るのか分かりません。 対処法を教えていただけないでしょうか? public void set_dictionary(String dict_filename) { } public int run(byte[] text, int start, int length, byte[] terms) { String type; //品詞の比較用 byte[] buf1 = new byte[1000]; //textの内容を一時的に格納しておくための配列1 byte[] buf2 = new byte[1000]; //textの内容を一時的に格納しておくための配列2 int i, j, k, count1, count2, FLG; count1 = 0; count2 = 0; k = 0; FLG = 0; for(i = start; i < length; i++) { if(text[i] == '\t') { FLG = 1; count2 = 0; } else if(text[i] == ' ') { FLG = 0; count1 = 0; } else { if(FLG == 1) { buf2[count2++] = text[i]; } else if(FLG == 0) { buf1[count1++] = text[i]; } } if((count2 == 5)&&(FLG == 1)) { type = new String(buf2, 0, 4); If(type.compareTo("名詞") == 0); { for(j = 0; j < count1; j++) { terms[k++] = buf1[j]; } terms[k++] = '/'; } count2 = 0; FLG = 2; } } return k; //term中のデータの長さを返す }

  • Vectorと配列

    お世話になります。 GUIから3つのString文字列を受け取り、追加ボタンを押した時点でVector(List)に格納し、登録ボタンを押してはじめてDBにデータを格納させたいのですが、 Vector list = new Vector(); String addData[] = {txta.getText(), txtb.getText(), txtc.getText()}; for(int i=0; i<addData.length; i++){ list.addElement(addData[i]); } しかし、連続してデータを追加するとlistには {data1,data2,data3,data4,data5,data6} のように入ってしまいます。 これを {data1,data2,data3} {data4,data5,data6} のようにlistに格納するにはどうすればいいでしょうか? ご教授頂ければ幸いです。 よろしくお願いします。

    • ベストアンサー
    • Java
  • Vectorのポインタが入ったvector

    windows Vista sp1, Visual C++ 2008でC++の勉強をしています。 Vectorへのポインタが入ったvectorを使うプログラムを書いているのですがうまくいかず、困っています。 どういうプログラムかというと、 入力ファイルの">"という記号を区切りとして、その間にある各行をひとまとめのグループとしてvectorにいれます。 さらに各vectorのポインタをべつのvectorに入れます。 最終的に区切りの数だけvectorができ、入力ファイルを読み終わった後に すべてのvectorを"各グループのポインタが入ったvector"からループ処理ですべて出力する、というものです。 /入力ファイル input.txt/ > human cat dog > beetle dragonfly spider > salmon saury catfish > vector1には human cat dog vector2にはbeetle dragonfly spider vector3にはsalmon saury catfish が入り、 別のvectorにそれぞれのvectorのポインタをいれ、 最後にこのvectorをつかって全ファイル内容を出力するというものです。 具体的に書くと、 ">"の区切りごとの各行のstringを入れるvectorとしてeach_vector。 each_vectorのポインタを入れるvectorをvector_of_ptr_each_vectorとします。 ">"を認識するごとに new で each_vectorの領域を確保し、そのポインタをvector_of_ptr_each_vectorに追加していき、">"のない行のstringを each_vectorに入れます。 ファイルの読み込みが終わった後でvector_of_ptr_each_vectorからイテレータを使って各vector(each_vector)の全要素をそれぞれ出力する、というものです。 以下のようにコードを書きました。 #include <fstream> #include <string> #include <vector> #include <iostream> using namespace std; int main( ) { ifstream ifs("input.txt"); string buf; std::vector<string> each_vector; std::vector<std::vector<string> *> vector_of_ptr_each_vector; while(ifs && getline(ifs, buf)) { if(buf[0] == '>'){ std::vector<string>* ptr_eachvector ; ptr_eachvector = new std::vector<string>; each_vector = *ptr_eachvector ; vector_of_ptr_each_vector.push_back(ptr_eachvector) ; } each_vector.push_back(buf) ; } printf("\n output from vector of ptr of vector\n"); std::vector<std::vector<string> *>::iterator it_b = vector_of_ptr_each_vector.begin(); while( it_b != vector_of_ptr_each_vector.end() ) { std::vector<string>::iterator it_c = it_b->begin();    //エラー1 while( it_c != it_b->end() ) //エラー2 { cout << *it_c << endl; ++it_c; } ++it_b; } return 0; } ですが、エラーでビルドされず、 std::vector<string>::iterator it_c = it_b->begin(); の行に関して error C2839: invalid return type 'std::vector<_Ty> **' for overloaded 'operator ->' error C2039: 'begin' : is not a member of 'std::_Vector_iterator<_Ty,_Alloc>' while( it_c != it_b->end() )   の行に関して error C2839: invalid return type 'std::vector<_Ty> **' for overloaded 'operator ->' 1> with 1> [ 1> _Ty=std::string 1> ] error C2039: 'end' : is not a member of 'std::_Vector_iterator<_Ty,_Alloc>' 1> with 1> [ 1> _Ty=std::vector<std::string> , 1> _Alloc=std::allocator<std::vector<std::string> > 1> ] fatal error C1903: unable to recover from previous error(s); stopping compilation というようなエラーが出ます。 vectorのポインタを入れたvectorの扱い、特にイテレータに関して問題があると思うのですが原因が分かりません。 また、new でのeach_vectorの領域確保の方法も怪しいという感じがします。 解決策、アドバイスありましたらよろしくお願いします。

  • vectorの中にmap

    vectorの中にmapを入れて 添字:ノードID [どのノードから来たのか|それまでのコスト] を表現しようと考えています. #include<iostream> #include<vector> #include<map> #include<list> // MACROS #define UNDEF -1 // PROTOTYPE DCLARE void init_path(std::vector<std::map<char, int> >, int size); int main(void) { //source -> source node // //size -> the number of node // //path -> store path infomation // ex: // path[1]: 1 is node id // char : from node id // cost : how cost from source to here // //adj -> show adjacency list eace node int source; int size; std::vector<std::map<char, int> > path; std::vector<std::list<char> > adj; size = 5; std::cout << "before" << std::endl; init_path(path, size); std::cout << "after" << std::endl; std::map<char, int>::iterator it; for(int i = 0; i < size; i++) { it = path[i].begin(); // std::cout << it->first << ":" << it->second << std::endl; } return 0; } void init_path(std::vector<std::map<char, int> > path, int size) { std::map<char, int> init; init.insert( std::map<char, int>::value_type('-', UNDEF) ); for(int i = 0; i < size ; i++) { path.push_back(init); } return; } *結果 before after Segmentation fault となり初期化をする所までは正常に動いたっぽいのですが どこが悪いのかわかりません(おそらくイテレータあたりかと思うのですが・・・・ 具体的にどうしたらいいのか分からないのでご指導ねがいます.

専門家に質問してみよう