[英]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.