簡體   English   中英

C ++ 11二維數組析構函數分割錯誤

[英]C++11 Bi-dimensional Array Destructor Segmentation Fault

這個問題讓我大吃一驚...我對C ++的經驗(實際上是每個OO編程范例)都很少,但是我找不到解決問題的方法...為什么我的析構函數使我在復制過載賦值時遇到問題? 感謝您的幫助,祝您有美好的一天

矩陣

#ifndef MATRICE_H_
#define MATRICE_H_

typedef double tipoelem;

class matrice {
  public:
    matrice(int, int, tipoelem inizializzatore = 0); /* costruttore */
    ~matrice(void);
    tipoelem leggiMatrice(int, int);
    void scriviMatrice(int, int, tipoelem);
    void prodottoScalare(tipoelem);
    matrice matriceTrasposta(void);
    matrice matriceProdotto(matrice& M);
    matrice& operator=(const matrice&);
    void rand(void);
    void stampa(void);
  private:
    int righe;
    int colonne;
    tipoelem **elementi;
};

#endif /* MATRICE_H_ */

矩陣文件

#include "matrice.h"
#include <stdlib.h>
#include <iostream>
// costruttore
matrice::matrice(int r, int c, tipoelem inizializzatore){
  this->colonne = c;
  this->righe = r;

  // allocazione dinamica della matrice
  elementi = new tipoelem*[righe];
  for (auto i=0; i!=righe; i++)
      this->elementi[i] = new tipoelem[colonne];

  // inizializzazione degli elementi
  for (auto i=0; i!=righe; i++)
      for(auto j=0; j!=colonne; j++)
          this->elementi[i][j] = inizializzatore;
}

matrice::~matrice(void){
    for(auto j=0;j<this->colonne;++j){
        delete[] this->elementi[j];
    }
    delete[] this->elementi;
}

tipoelem matrice::leggiMatrice(int i, int j){
    return elementi[i][j];
}

void matrice::scriviMatrice(int i, int j, tipoelem scrittura){
    elementi[i][j] = scrittura;
    return;
}

void matrice::prodottoScalare(tipoelem scalare){
    for(auto i = 0; i<righe;i++)
        for(auto j = 0; j<colonne;j++)
            elementi[i][j]=elementi[i][j]*scalare;
    return;
}

matrice matrice::matriceTrasposta(void){
    matrice trasposta(colonne, righe);

    for(auto i=0; i<righe;i++)
        for(auto j=0; j<colonne;j++)
            trasposta.scriviMatrice(j,i,leggiMatrice(i,j));
    return trasposta;
}

matrice matrice::matriceProdotto(matrice& M){
    matrice prodotto(righe, colonne);

    for(auto i=0; i<righe;i++)
        for(auto j=0; j<righe;j++)
            prodotto.scriviMatrice(i,j,(matrice::leggiMatrice(i,j)*M.leggiMatrice(i,j)));
    return prodotto;
}

matrice& matrice::operator=(const matrice &m){
    if(this != &m){
        if(colonne != m.colonne || righe != m.righe){
            this->~matrice();
            this->righe = m.righe;
            this->colonne = m.colonne;
            matrice(righe,colonne);
        }
        for(auto i=0;i!=righe;i++)
            for(auto j=0;j!=colonne;j++)
                elementi[i][j] = m.elementi[i][j];
    }
    return (*this);
}

void matrice::rand(void){
    for(auto i=0; i<righe;i++)
        for(auto j=0;j<colonne;j++)
            matrice::scriviMatrice(i,j,(random() % 100));
    return;
}

void matrice::stampa(void){
    for(auto i=0; i<righe;i++){
        for(auto j=0; j<colonne;j++)
            std::cout << elementi[i][j] << " ";
    std::cout << std::endl;
    }
}

TestMatrice.cpp(用於測試建議)

#include <iostream>
#include "matrice.h"

int main(void){

    matrice A(3,2), T(2,3);
    A.rand();
    std::cout <<"Stampa A" << std::endl;
    A.stampa();
    std::cout << "Stampa Trasposta T" << std::endl;
    T = A.matriceTrasposta();
    T.stampa();

    std::cout << std::endl;

    std::cout << "Stampa B" << std::endl;
    matrice B(4,4);
    B.stampa();
    std::cout << "Stampa copia t in b" << std::endl;
    B = T;
    B.stampa();

    return (0);
}

Tx

聚苯乙烯

控制台輸出和調試信息:

Stampa A
83 86 
77 15 
93 35 
Stampa Trasposta T
83 77 93 
86 15 35 

Stampa B
0 0 0 0 
0 0 0 0 
0 0 0 0 
0 0 0 0 
Stampa copia t in b
83 77 93 
86 15 35 
*** Error in `/home/ibanez89/UniBa/Workspace/[ASD 2015]/[ASD]Esercitazione_lab3/Debug/[ASD]Esercitazione_lab3': free(): invalid pointer: 0x0000000001f63e10 ***
======= Backtrace: =========
/usr/lib/libc.so.6(+0x72055)[0x7fb1eb9c6055]
/usr/lib/libc.so.6(+0x779a6)[0x7fb1eb9cb9a6]
/usr/lib/libc.so.6(+0x7818e)[0x7fb1eb9cc18e]
/home/ibanez89/UniBa/Workspace/[ASD 2015]/[ASD]Esercitazione_lab3/Debug/[ASD]Esercitazione_lab3[0x400e82]
/home/ibanez89/UniBa/Workspace/[ASD 2015]/[ASD]Esercitazione_lab3/Debug/[ASD]Esercitazione_lab3[0x400c3e]
/usr/lib/libc.so.6(__libc_start_main+0xf0)[0x7fb1eb974610]
/home/ibanez89/UniBa/Workspace/[ASD 2015]/[ASD]Esercitazione_lab3/Debug/[ASD]Esercitazione_lab3[0x400a09]
======= Memory map: ========
00400000-00402000 r-xp 00000000 08:03 14945604                           /home/ibanez89/UniBa/Workspace/[ASD 2015]/[ASD]Esercitazione_lab3/Debug/[ASD]Esercitazione_lab3
00601000-00602000 rw-p 00001000 08:03 14945604                           /home/ibanez89/UniBa/Workspace/[ASD 2015]/[ASD]Esercitazione_lab3/Debug/[ASD]Esercitazione_lab3
01f52000-01f84000 rw-p 00000000 00:00 0                                  [heap]
7fb1e4000000-7fb1e4021000 rw-p 00000000 00:00 0 
7fb1e4021000-7fb1e8000000 ---p 00000000 00:00 0 
7fb1eb954000-7fb1ebaef000 r-xp 00000000 08:02 1051822                    /usr/lib/libc-2.22.so
7fb1ebaef000-7fb1ebcee000 ---p 0019b000 08:02 1051822                    /usr/lib/libc-2.22.so
7fb1ebcee000-7fb1ebcf2000 r--p 0019a000 08:02 1051822                    /usr/lib/libc-2.22.so
7fb1ebcf2000-7fb1ebcf4000 rw-p 0019e000 08:02 1051822                    /usr/lib/libc-2.22.so
7fb1ebcf4000-7fb1ebcf8000 rw-p 00000000 00:00 0 
7fb1ebcf8000-7fb1ebd0e000 r-xp 00000000 08:02 1052090                    /usr/lib/libgcc_s.so.1
7fb1ebd0e000-7fb1ebf0d000 ---p 00016000 08:02 1052090                    /usr/lib/libgcc_s.so.1
7fb1ebf0d000-7fb1ebf0e000 rw-p 00015000 08:02 1052090                    /usr/lib/libgcc_s.so.1
7fb1ebf0e000-7fb1ec00b000 r-xp 00000000 08:02 1051873                    /usr/lib/libm-2.22.so
7fb1ec00b000-7fb1ec20a000 ---p 000fd000 08:02 1051873                    /usr/lib/libm-2.22.so
7fb1ec20a000-7fb1ec20b000 r--p 000fc000 08:02 1051873                    /usr/lib/libm-2.22.so
7fb1ec20b000-7fb1ec20c000 rw-p 000fd000 08:02 1051873                    /usr/lib/libm-2.22.so
7fb1ec20c000-7fb1ec37e000 r-xp 00000000 08:02 1061398                    /usr/lib/libstdc++.so.6.0.21
7fb1ec37e000-7fb1ec57e000 ---p 00172000 08:02 1061398                    /usr/lib/libstdc++.so.6.0.21
7fb1ec57e000-7fb1ec588000 r--p 00172000 08:02 1061398                    /usr/lib/libstdc++.so.6.0.21
7fb1ec588000-7fb1ec58a000 rw-p 0017c000 08:02 1061398                    /usr/lib/libstdc++.so.6.0.21
7fb1ec58a000-7fb1ec58e000 rw-p 00000000 00:00 0 
7fb1ec58e000-7fb1ec5b0000 r-xp 00000000 08:02 1051821                    /usr/lib/ld-2.22.so
7fb1ec763000-7fb1ec769000 rw-p 00000000 00:00 0 
7fb1ec7ad000-7fb1ec7af000 rw-p 00000000 00:00 0 
7fb1ec7af000-7fb1ec7b0000 r--p 00021000 08:02 1051821                    /usr/lib/ld-2.22.so
7fb1ec7b0000-7fb1ec7b1000 rw-p 00022000 08:02 1051821                    /usr/lib/ld-2.22.so
7fb1ec7b1000-7fb1ec7b2000 rw-p 00000000 00:00 0 
7ffdcc751000-7ffdcc772000 rw-p 00000000 00:00 0                          [stack]
7ffdcc794000-7ffdcc796000 r--p 00000000 00:00 0                          [vvar]
7ffdcc796000-7ffdcc798000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

該問題與您的分配運算符有關。 您正在此行上顯式調用析構函數:

 this->~matrice();

應該顯式調用析構函數,unlesss你使用placement-new 發生的事情是,當對象超出范圍時調用“正常”析構函數時,您將兩次分配相同的指針值,從而導致發生未定義的行為。

如果我們結合針對析構函數修復的答案,那么可以輕松編寫您的賦值運算符。 但是,您的代碼缺少用戶定義的副本構造函數。 遵循3規則 ,如果您具有用戶定義的析構函數,則應該存在用戶定義的副本構造函數和賦值運算符。

因此,讓我們為您的類定義一個復制構造函數:

首先,該類缺少此內容:

matrice(const matrice& rhs);

我們想將rhs復制到新對象。 實現可以如下所示:

matrice::matrice(const matrice& rhs) : colonne(rhs.colonne), 
                                       righe(rhs.righe), 
                                       elementi(new tipoelem*[rhs.righe])
{
    for (auto i = 0; i != righe; i++)
        this->elementi[i] = new tipoelem[colonne];

    for (auto i = 0; i != righe; i++)
        for (auto j = 0; j != colonne; j++)
            this->elementi[i][j] = rhs.elementi[i][j];
}

因此,我們從rhs復制所有項目,創建矩陣,然后將矩陣值從rhs復制到this

一旦有了這個,就可以使用Copy / Swap Idiom輕松編寫賦值運算符:

matrice& matrice::operator=(const matrice &m) 
{
    matrice temp(m);
    std::swap(temp.colonne, colonne);
    std::swap(temp.righe, righe);
    std::swap(temp.elementi, elementi);
    return *this;
}

通過創建rhs的臨時副本(副本構造函數完成了此工作),然后用該臨時副本換出現有對象的內部,可以工作。 由於臨時對象現在已交換了舊數據,因此當它死亡時(在函數末尾),該舊數據將隨之刪除。 簡而言之,這就是復制/交換的作用,以及為什么必須具有有效的復制構造函數和析構函數才能使用它。

一旦有了這個,並結合其他答案中的針對析構函數的修復,我們將看到代碼現在不會崩潰:

完整的例子

請注意:我使用常量100.0代替rand() ,因為您的代碼由於random返回void而無法編譯。

你把殖民地與嚴厲混為一談

matrice::~matrice(void){
    for(auto j=0;j<this->righe;++j){
                      // ^^^^^^
        delete[] this->elementi[j];
    }
    delete[] this->elementi;
}

..那里...

matrice matrice::matriceProdotto(matrice& M){
    matrice prodotto(righe, colonne);

    for(auto i=0; i<righe;i++)
        for(auto j=0; j<colone ;j++)
                     // ^^^^^^^
            prodotto.scriviMatrice(i,j,(matrice::leggiMatrice(i,j)*M.leggiMatrice(i,j)));
    return prodotto;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM