2012-02-10 17 views
2

多くの研究の後でさえ、私はなぜvalgrindからこのエラーが出ているのか理解していません。 クラスのスパイクがあります(擬似二重リンクリストを実装しています)Valgrind無効な読み取り/書き込みリスト

class spike 
{ 
    int s_cell; 
    int s_begin; 
    int s_number; 
    int s_type; 
    spike *s_previous; 
    spike *s_next; 

    spike *s_origin; // pointer for original spike or itself 
        // (in the very first spike_data) 

    spike *s_derive; // pointer for the spike in the derived class 
        // (note, that sometimes there are 2 or more high 
        // order spike_data in parallel; the pointer is only to one) 
public: 
    spike(int c, int b, int n, int typ=c_normal) 
    { 
    s_cell = c; 
    s_begin = b; 
    s_number = n; 
    s_previous = NULL; 
    s_next = NULL; 
    s_derive = NULL; 
    s_origin = this; 
    s_type = typ; 
    } 

    ~spike() 
    { 
    kill(); 
    } 

クラスspike_data。

class spike_data 
{ 
protected: 
    int sd_mode; 
    int sd_size; 
    int sd_number;  // the whole number of spikes 
    int sd_file;  // the number of files for analysis 
    int *sd_file_name; // the names of files used in the analysis 
    int sd_cells;  // the whole number of different cells 

    spike **sd_array; // array of all spikes 
    spike *sd_first[c_maxcells]; // array of the first entries of spikes 
    spike **sd_file_st; // spikes in array for indication of beginning of the new files 

// And here is the part that's getting the error 
// (it is happening when i try to release) 
void spike::kill() 
{ 
    // delete a cell from all references and t becomes "dead" 
    // actual release of memory is done in renumerate 
    try 
    { 
    if (s_previous != NULL) 
     s_previous->s_next = s_next; 
    if (s_next != NULL) 
     s_next->s_previous = s_previous; 
    if (s_origin && s_origin != this) 
    { 
     int tmp = 1; 
    while(tmp == 1) { 
     if (s_origin != NULL) { 
      if (s_origin->s_derive != NULL) { // LINE 674 
       if (s_origin->s_derive != this) { // LINE 675 
         s_origin=s_origin->s_derive; 
        } 
        else tmp = 0; 
       } 
      else tmp = 0;      
        } 
      else tmp = 0; 
    } 

     s_origin->s_derive=NULL; // LINE 685 
    } 
    } 
    catch (...) 
    { 
    } 
    s_next = NULL; 
    s_previous = NULL; 
    s_origin = NULL; 
} 


spike_data::~spike_data() 
{ 

if(sd_array!=NULL) 
{ 
    for(int i=0;i<sd_number;i++) 
     delete sd_array[i]; // LINE 697 

    delete[] sd_array; 
    sd_array=NULL; 
} 
if(sd_file_st!=NULL) 
{ 
    delete[] sd_file_st; 
    sd_file_st=NULL; 
} 
if(sd_file_name!=NULL) 
{ 
    delete[] sd_file_name; 
    sd_file_name=NULL; 
} 
} 

申し訳ありませんが、コードがindigestある場合、だから、ここにあるそれは私のものではないが、それはまだ大丈夫だ...

Invalid read of size 4 
==2079== at 0x806B0DF: spike::kill() (spikes.cpp:674) 
==2079== by 0x8067D26: spike::~spike() (spike.h:288) 
==2079== by 0x806B174: spike_data::~spike_data() (spikes.cpp:689) 
==2079== by 0x805CB1F: spike_anal::~spike_anal() (spikea.cpp:151) 
==2079== by 0x8061C1E: statistical_analysis(spike_group*, spike_data*) (spikeg.cpp:264) 
==2079== by 0x804B37E: calculate_something(int, int) (all.cpp:422) 
==2079== by 0x8059805: real_main(int, char const*) (simple.cpp:742) 
==2079== by 0x804DC20: main (hello.cpp:66) 
==2079== Address 0x5d8f534 is 28 bytes inside a block of size 32 free'd 
==2079== at 0x4023881: operator delete(void*) (vg_replace_malloc.c:387) 
==2079== by 0x806B17C: spike_data::~spike_data() (spikes.cpp:697) 
==2079== by 0x805CB1F: spike_anal::~spike_anal() (spikea.cpp:151) 
==2079== by 0x8061C06: statistical_analysis(spike_group*, spike_data*) (spikeg.cpp:264) 
==2079== by 0x804B37E: calculate_something(int, int) (all.cpp:422) 
==2079== by 0x8059805: real_main(int, char const*) (simple.cpp:742) 
==2079== by 0x804DC20: main (hello.cpp:66) 
==2079== 
==2079== Invalid read of size 4 
==2079== at 0x806B0EC: spike::kill() (spikes.cpp:675) 
==2079== by 0x8067D26: spike::~spike() (spike.h:288) 
==2079== by 0x806B174: spike_data::~spike_data() (spikes.cpp:689) 
==2079== by 0x805CB1F: spike_anal::~spike_anal() (spikea.cpp:151) 
==2079== by 0x8061C1E: statistical_analysis(spike_group*, spike_data*) (spikeg.cpp:264) 
==2079== by 0x804B37E: calculate_something(int, int) (all.cpp:422) 
==2079== by 0x8059805: real_main(int, char const*) (simple.cpp:742) 
==2079== by 0x804DC20: main (hello.cpp:66) 
==2079== Address 0x5d8f534 is 28 bytes inside a block of size 32 free'd 
==2079== at 0x4023881: operator delete(void*) (vg_replace_malloc.c:387) 
==2079== by 0x806B17C: spike_data::~spike_data() (spikes.cpp:697) 
==2079== by 0x805CB1F: spike_anal::~spike_anal() (spikea.cpp:151) 
==2079== by 0x8061C06: statistical_analysis(spike_group*, spike_data*) (spikeg.cpp:264) 
==2079== by 0x804B37E: calculate_something(int, int) (all.cpp:422) 
==2079== by 0x8059805: real_main(int, char const*) (simple.cpp:742) 
==2079== by 0x804DC20: main (hello.cpp:66) 
==2079== 
==2079== Invalid write of size 4 
==2079== at 0x806B10A: spike::kill() (spikes.cpp:685) 
==2079== by 0x8067D26: spike::~spike() (spike.h:288) 
==2079== by 0x806B174: spike_data::~spike_data() (spikes.cpp:689) 
==2079== by 0x805CB1F: spike_anal::~spike_anal() (spikea.cpp:151) 
==2079== by 0x8061C1E: statistical_analysis(spike_group*, spike_data*) (spikeg.cpp:264) 
==2079== by 0x804B37E: calculate_something(int, int) (all.cpp:422) 
==2079== by 0x8059805: real_main(int, char const*) (simple.cpp:742) 
==2079== by 0x804DC20: main (hello.cpp:66) 
==2079== Address 0x5d8f534 is 28 bytes inside a block of size 32 free'd 
==2079== at 0x4023881: operator delete(void*) (vg_replace_malloc.c:387) 
==2079== by 0x806B17C: spike_data::~spike_data() (spikes.cpp:697) 
==2079== by 0x805CB1F: spike_anal::~spike_anal() (spikea.cpp:151) 
==2079== by 0x8061C06: statistical_analysis(spike_group*, spike_data*) (spikeg.cpp:264) 
==2079== by 0x804B37E: calculate_something(int, int) (all.cpp:422) 
==2079== by 0x8059805: real_main(int, char const*) (simple.cpp:742) 
==2079== by 0x804DC20: main (hello.cpp:66) 

。私はspike_dataを殺したいとき、私はdelete sd_array [i]を呼び出し、spike => kill()のデストラクタを呼び出します。 最後にこのコードバグがあります。実行中に何度も使用されましたが、すべての計算が完了してメモリを解放する必要があるときには、動作しません。私はs_origin-> s_derive = NULLを置くと問題があると思います。しかし、uがより多くのコードが必要な場合は

ちょうど:)

は、このコードに取得するのに十分勇敢されている人のためにあなたにたくさんありがとう聞いて...それをつかむことができません!

良い週末

ニコ

+1

OMG投稿する前にコードの外観を編集してください!私はそれを編集しています – Eregrith

+0

なぜコードスタイルは、クラスの最初の行に動作しません取得しないでください。ごめんなさい。それとも、スタイルについて話しているのですか?うん、それは本当に拷問だと私は同意する。このコードをもっと見栄えの良いものに変更しようと思っています。それはロシア人のものです^^ – Nikkolasg

+0

私はそれを変更しました。それは良いです。 改行がないために失敗しました^^ – Eregrith

答えて

1

スパイクためデフォルトのコピーコンストラクタは、あなたがそれに気付かずに起動されたことが良い可能性があります。この場合、最初のデストラクタは正常に動作するかもしれませんが、2回目の呼び出しでvalgrindは投稿したもののようなメッセージをダンプします。あなたがC++ 11を使用している場合、これは、そうであるかどうかを確認するために

、追加:

public: 
    spike(const spike& rhs) = delete; 

をして、あなたのコードが示すコンパイルに失敗する必要があり、あなたがあなた自身のコピーを書くために必要コンストラクタ。

ではなく、でC++ 11を使用している場合は、独自のコピーコンストラクタを記述し、デバッグ中にブレークポイントが存在するかどうかを確認することができます。

+0

私はこのspike :: spike(const spike&rhs){}のようなコピーコンストラクタを作成し、しかし、プログラムは決して止まらないので、コピーコンストラクタを呼び出すことはありません:.../thxとにかく! – Nikkolasg

+0

オリジナルのプログラマは、(コンストラクタのコピーではなく古いコード)memcpy cmdをたくさん使います。例:dop =新しいスパイク* [sd_size]; memcpy(dop、sd_array、sizeof(spike *)* sd_number);私はそれに取り組むでしょう、そうかもしれません。 – Nikkolasg

+0

spikes.cpp:689とspikes.cpp:697にブレークポイントを配置します。ブレークポイントをヒットすると、解放されているメモリ位置が出力されます。次に、ブレークポイントを条件付きブレークポイントに変更して、変数がそのアドレスであるときに停止します。そのポイントにもう一度当たると、コールスタックに上がり、問題が表示されます。ここに決定論的なメモリバグがあります。デバッグするのが難しいはずはありません(あなたのコールスタックに厄介なスパゲティコードがない限り)。あなたはこれを捕まえるためにあなたの目や脳を少し使わなければなりません。 – kfmfe04

関連する問題