• ベストアンサー

newとdeleteな気がするエラー

以下のようなプログラムを書いているのですが、delete [] ang;の行を実行すると、 Debug Assertion Failed! Program: ...\Debug\pro.exe File: f:\dd\vctools\crt_bld\self_x86\crt\src\dbgdel.cpp Line: 52 Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) というエラーが発生します。 fscanfを書いてからうまくいかなくなってきたので、modtorがオーバーフローしてるのかな?とも思ったのですが、特にそれらしいものは見当たりません。 いったい何が原因なのでしょうか? よろしくお願いします。 #include<stdio.h> #include<string> using namespace std; void main(void){   int i;   int ret;   static const int anum=3;   static const int LoopMax=100;   double *modtor=new double[LoopMax*anum];   double *ang=new double[LoopMax*2*anum];   const string strlearned="A.csv";   const string strlearning="_learning.csv";   FILE *fpl;   FILE *fpvnmd;   errno_t err;   double outputv[anum]={0};   double tempd;   double *tarr=new double[LoopMax];   //delete [] tarr;      //ここで消すとエラーが消える   fopen_s(&fpl,strlearned.c_str(),"r");   printf("データ読み込み\n");   for(i=0;i<LoopMax;i++){     if(fscanf(fpl,"%[^,],%lf,%lf,%lf,%lf",&tempd,&modtor[anum*i],&modtor[anum*i+1],&modtor[anum*i+2])==EOF)break;   }   fclose(fpl);     delete [] ang;   delete [] tarr;   delete [] modtor; }

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

  • ベストアンサー
  • php504
  • ベストアンサー率42% (926/2160)
回答No.4

>この意味を余りよく知らないのです^^; これが原因なので意味を理解しないまま使ってはだめでしょう。 %[~]は文字列を読み込む指定子の1つです。(普通は%sですね) フォーマット系の可変引数の関数では引数の型チェックができません。 フォーマット指定子と実際の引数の型を合わせるのはプログラマの責任で型が合わないとこのようなバグを引き起こします。 >この「*」は何を意味しているのでしょうか? http://www.linux.or.jp/JM/html/LDP_man-pages/man3/scanf.3.html より引用 ------------------- 代入抑制文字"*"。 scanf() は変換指定に指示された通り入力を読み込むが、その入力は捨てられる。対応する pointer 引き数は必要なく、 scanf() が返す代入が成功した数にこの指定は含まれない。 ------------------- です。

glarelance
質問者

お礼

よく分かりました。 どうも有り難うございました。

その他の回答 (4)

  • php504
  • ベストアンサー率42% (926/2160)
回答No.5

4. 「元のままだと「5番目の引数が無いので、」とありますが、もとの場合、5番目の引数は、「&modtor[anum*i+1]」となっていると思うのですが、これはどういう意味なのでしょうか? フォーマット指定部分"%[^,],%lf,%lf,%lf,%lf"では5個の指定がありますが読み込む変数が &tempd &modtor[anum*i] &modtor[anum*i+1] &modtor[anum*i+2] の4個しかないということでしょう。 今回は個数の問題だけでもなく1個目の型があってないのも原因ですが。 データが 0.000000,0.000000,0.010127,0.210067 なら fscanf(fpl,"%lf,%lf,%lf,%lf",&tempd,&modtor[anum*i],&modtor[anum*i+1],&modtor[anum*i+2]) でも問題なかったのでは。

  • jmh
  • ベストアンサー率23% (71/304)
回答No.3

その「http://simd.jugem.jp/?eid=49」には「%[^,] を使用することにより、カンマ以外の_文_字_列_を読み込むという_指_定_が出来るわけです。」とありますが?

glarelance
質問者

お礼

あ、、、 文字列用の特殊指定子だったんですね。。。 どうも有り難うございました。

  • jmh
  • ベストアンサー率23% (71/304)
回答No.2

%[^,] に対して double tempd でいいの?

glarelance
質問者

お礼

>%[^,] に対して double tempd でいいの? これは、どういう意味なのでしょうか? 実は、%[^,]はhttp://simd.jugem.jp/?eid=49 に、こう書くとカンマを無視して読み込めるようになると書いてあったから、付けただけなもので、この意味を余りよく知らないのです^^;

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

if(fscanf(fpl,"%[^,],%lf,%lf,%lf,%lf",&tempd,&modtor[anum*i],&modtor[anum*i+1],&modtor[anum*i+2])==EOF)break; を if(fscanf(fpl,"%*[^,],%lf,%lf,%lf",&modtor[anum*i],&modtor[anum*i+1],&modtor[anum*i+2])!=anum)break; にしてみよう。 「scanfは引数が足りなくても知ったこっちゃない」と「scanfは読み捨て可能」と、2つの事を覚えましょう。 元のままだと「5番目の引数が無いので、メモリ上にあったゴミをアドレスだと思って、そこに実数値を格納し、メモリがグチャグチャに壊れる」とか「カンマ以外を読み捨てる時、読み捨てるバイト数がdoubleオブジェクトのサイズを超えてたら、メモリがグチャグチャに壊れる」って事が起きます。 つか、 >  //delete [] tarr;      //ここで消すとエラーが消える の状態で実行時エラーが出ないで動いちゃうのが不思議。偶然「壊れても構わないメモリが壊れているだけ」なんだろうなあ。

glarelance
質問者

お礼

解答有り難うございます。 if(fscanf(fpl,"%*[^,],%lf,%lf,%lf",&modtor[anum*i],&modtor[anum*i+1],&modtor[anum*i+2])!=anum)break; について、いくつか質問があります。 1. 「%*[^,]」という記述がありますが、この「*」は何を意味しているのでしょうか? 2. 「scanfは引数が足りなくても知ったこっちゃない」と「scanfは読み捨て可能」とのことですが、ここでいう引数とは、「,&modtor[anum*i],&modtor[anum*i+1],&modtor[anum*i+2]」の部分のことを指しているのでしょうか? また、私は、一列目の値を「,&tempd」で空読みするようにしてみていたのですが、chie65535さんの方では、この部分がなくなり、%lfの数も3つになっていますが、このことに関係しているのでしょうか? もしそうなら、どのように関係しているのでしょうか? 3. chie65535さんは、fscanfの戻り値が、anumでなければ終了としていますが、これは行の項目数が3でなければ、想定している項目数と違うから終了。という解釈で良いんでしょうか? 4. 「元のままだと「5番目の引数が無いので、」とありますが、もとの場合、5番目の引数は、「&modtor[anum*i+1]」となっていると思うのですが、これはどういう意味なのでしょうか? 私の疑問は、どういうデータファイルを読み込んでいるのか、書き忘れてたから出ている部分もあるのかな・・・ 私が使っているデータは、 0.000000,0.000000,0.010127,0.210067 0.010000,0.000000,0.059026,0.178709 0.020000,0.000000,0.096992,0.153418 ・ ・ ・ 0.990000,0.000000,-0.020241,0.019949 という、100行のデータになっています。 長々となってしまいましたが宜しくお願いします。

関連するQ&A

  • newとdelete

    動的にaaa[5][40]という配列を作りたいのですけど,以下のプログラムでよろしいでしょうか? aaa = new double *[5]; for(int p = 0; p < 5; p++){ aaa[p] = new double [40]; } また,これをdeleteするときはどのようにすればよろしいのでしょうか? どうぞよろしくお願いいたします.

  • 自作の行列クラスを継承するさいにエラーがでます

    現在、c++の学習で、自作の基底行列クラスMatrixを作成し、このクラスを継承して新たにlduMatrixを作成する事を考えています。 が、継承し、 lduMatrix a( 3, 3); a = 3; とすると、 main.C:13: warning: passing ‘double’ for argument 1 to ‘lduMatrix::lduMatrix(int)’ というエラーがでてコンパイルできずにいます。その一方で、 lduMatrix a(3,3, 3.14); とするとコンパイルはとおり、lduMatrix行列の各要素(a[1][1]など)の値をプリントさせると、[[3.14]]の値が入っていることを確認しております。 どこが間違っているのか御指導いただけると幸いです。 以下、クラスの中身です。よろしくおねがいします。 《Class: Matrix》 #include <iostream> class Matrix{ private: //! Size of row and column in Matrix int row_, col_; //! Row pointers double** m_; //! Allocate function for row-pointers void allocate(); public: Matrix(); //! Constructor with given matrix size Matrix( const int, const int ); //! Constructor with given matrix size and value fro all elements Matrix( const int, const int, const double ); //! Destructor ~Matrix(); ・・・省略・・・ double* operator[]( const int ); double* operator[]( const int ) const ; void operator=( const double ); }; /* Private functions *********************************************** */ void Matrix::allocate() { m_ = new double* [row_]; m_[0] = new double [row_*col_]; for ( int i=1; i<row_; i++ ){ m_[i] = m_[i-1] + col_; } } /* Destructor ****************************************************** */ Matrix::~Matrix(){ delete[] m_[0]; delete[] m_; } /* Constructors **************************************************** */ // NULL constructor Matrix::Matrix() : row_(0), col_(0), m_(NULL) {} // Constructor with given matrix size Matrix::Matrix( const int row, const int col ) : row_(row), col_(col) { allocate(); } // Constructor with given matrix size and value for all elements Matrix::Matrix( const int row, const int col, const double s ): row_(row), col_(col) { allocate(); double* m = m_[0]; for ( int i=0; i<row_*col_; i++ ){ m[i] = s; } } 《省略》 /* Member operators ************************************************ */ double* Matrix::operator[]( const int i ){ return m_[i]; } void Matrix::operator=( const double t ){ double* m = m_[0]; int nm = row_*col_; for ( int i=0; i<nm; i++ ) { m[i] = t; } } 《Class: lduMatrix》 class lduMatrix : public Matrix{ public: lduMatrix(); lduMatrix( const int ); lduMatrix( const int, const double ); }; lduMatrix::lduMatrix() {} lduMatrix::lduMatrix( const int mSize ) : Matrix( mSize, mSize, 0.0 ) {} lduMatrix::lduMatrix( const int mSize, const double s ) : Matrix( mSize, mSize, s ) {}

  • C++:構造体:newで入れ子:deleteは?

    C++で以下のような構造体を使っています。(本当は他にもメンバが有ります) // ----- typedef struct{  int *npMember; }Test_t; // ----- これをクラスのメンバ変数で // ----- Test_t *m_tpTestStruct; // ----- とし、関数の中で // ----- m_tpTestStruct = new Test_t[10]; for (int i = 0; i < 10; i++) {  m_tpTestStruct[i].npMember = new int[100]; } // ----- というようにメモリを割り当てています。 これを解放する時は、 // ----- for (int i = 0; i < 10; i++) {  delete [] m_tpTestStruct[i].npMember; } delete [] m_tpTestStruct; // ----- で、良いのでしょうか? それとも、他の書き方が必要なのでしょうか?

  • delete演算子オーバーロードについて

    delete演算子オーバーロードする際、 デストラクタが呼び出される困っています。 例えば、 void* operator new(size_t size, const char* filename , int line , const char* funcname ); とnew演算子をグローバル定義します。 すると、意図通りnew演算子がCallされ、対応するコントラクタも 問題なくCallされます。 そして、上記new定義にペアとなるdelete演算子もグローバル定義します。 void operator delete(void* pMem, const char* filename , int line , const char* funcname ); 通常どおりdeleteで呼び出してしまうと、標準のdeleteがcallされてしまうため、 #define MYELETE(s) operator delete( (void*)(s) , __FILE__ , __LINE__ , __FUNCTION__ ) 上記のようなカスタムマクロを定義してCallしています。 オーバーロード定義されたアドレスがCallされるところまで、 意図通りなのですが、肝心のデストラクタがCallされません。 型が判明している場合、 単体でデストラクタを明示的に呼び出すことはできますが、 任意のポインタのデストラクタを明示的に呼び出す方法は ありますでしょうか?

  • 動的配列を宣言するためにnew演算子とdelete演算子を用いる方法が

    動的配列を宣言するためにnew演算子とdelete演算子を用いる方法があります。 2次元配列は以下のように宣言して作れるのは分かったのですが、 (実際に使って動かしてみました。) int **pp; pp = new int*[ROW]; // 行を作る for(int i = 0; i < ROW; i++) // 列を作る pp[i] = new int[COL]; http://www.asahi-net.or.jp/~uc3k-ymd/Lesson/Section02/section02_07.html(引用) 3次元配列をどのように作ったらいいか分かりません。 教えてください。宜しくお願いします。

  • ファイル入力のエラー

    以下のファイルを配列に読み込むプログラムを作っています。 1987 1100 12 23 2.467164 0.75153 1989 1202 12 31 2.456249 0.72896 1990 1204 9 28 2.484802 0.763903 1991 1206 11 26 2.520005 0.750182 1985 1207 9 26 2.499319 0.749116 以下の通りプログラムを組んでみました。 コンパイルしたところ、出力はされませんでした。 エラーも出ていないので、入力、出力などどこが悪いのかわかりません。 ほとんど初心者です。間違いが分かる方、よろしくお願いします。 #include<stdio.h> #define SIZE 5 main() { int a, b, c, d, i; static int year[SIZE],month[SIZE],day[SIZE],code[SIZE];   double e, f; static double latitude[SIZE],longitude[SIZE]; FILE *fp; fp=fopen("c\distance.dat","r"); while((fscanf(fp,"%d%d%d%d%lf%lf",&a,&b,&c,&d,&e,&f)) !=EOF) { year[i]=a; month[i]=b; day[i]=c; code[i]=d; latitude[i]=e; longitude[i]=f; i++; printf("%13d%8d%8d%8d%9.6lf%9.6lf\n",&a,&b,&c,&d,&e,&f); } fclose(fp); return(0); }

  • c++のnew演算子をオーバーロードできるものの、

    c++のnew演算子をオーバーロードできるものの、 delete演算子をオーバーロードできなくて悩んでいます。 コンパイルは通るのですが、ランタイム時に ペアとなるdeleteが呼ばれません。 inline void* operator new(size_t size, const char* filename , int line , const char* funcname ) { return my_local_malloc( size , filename , line , funcname ); } inline void operator delete(void* pMem, const char* filename , int line , const char* funcname ) { my_local_free( pMem , filename , line , funcname ); } deleteも確実にオーバーロードできる方法を ご存知のかた、お教え願います。

  • 正規乱数がうまく使えない

    正規乱数をつかってプログラムを組みたいのですが staticでないメソッドnextGaussian()をstatic コンテキストから参照することはできません というエラーが出てコンパイルできません。 public class sample{ public static void main(String[] args) { int n = 10; double z[] = new double[2*n]; for(int i = 0; i<n; i++){ z[2*i ] = Random.nextGaussian(); z[2*i+1] = Random.nextGaussian();} } } 申し訳ないのですがお手上げなので原因と解決法を教えて いただければと思います。よろしくお願いします。

  • new int[変数]で確保しても良いんですか?

    Javaでの配列の確保の方法です。 int size = 100; int[] array = new int[size]; のような確保の方法はどの環境・コンパイラでも思い通りの動作をしてくれますか? C言語では、このような書き方で確保することはできなかったので、Javaでは可能なのか心配で質問しました。 「動的」という意味がまだ完全にわかっていないのですが、上記のような変数の確保は、動的とはいえないのですか?sizeの値をユーザーから受け取れば、確保する大きさはいつも違うようになると思うのですが・・・。 ちなみに下記のようなプログラムで配列の確保を使おうとしています。 static int[] toIntArray(String[] strs){   int[] array = new int[strs.length]; // ←ここで 確保しています。   for(int i = 0; i < strs.length; i++){    array[i] = Integer.valueOf(strs[i]).intValue();   }   return array; } 上記のプログラムはStringの配列からintの配列に変換することを目的にしています。

    • ベストアンサー
    • Java
  • 文字列のメンバ変数を外部変数のように扱いたい

    済みません。質問なのですが、 メンバ変数を外部変数のように扱うにはどうしたらよいのでしょうか? int型などの場合、 class test{ static const int a; }; const int test::a = 10; とすればよいですよね? これをcharの配列にして class test{ static char a[7][32]; }; char test::a[0] = "test"; とすると サイズが0の配列を割り当てまたは宣言しようとしました というコンパイルエラーがでてしまいます…。 多次元配列の場合はstatic変数としてもてないのでしょうか? char** として宣言してもどこでnewを行えばよいか解りません。 コンストラクタの中で行えば そこでstaticではなくなってしまいますし…。 後、できればstringクラスの配列で持ちたいのですが #include <string> class test{ static string test[7]; }; string test::test[0] = "aaa"; なんてことができますでしょうか? 質問内容が解りにくいかも知れませんが どうか教えてください。 宜しくお願いいたします。

専門家に質問してみよう