Проблема с удалением 2d-массива в классе шаблонов

#c #arrays #templates #dynamic #netbeans

#c #массивы #шаблоны #динамический #netbeans

Вопрос:

Итак, я работал над программой, в которой я использую 2d-массивы и шаблоны для печати матриц на Netbeans 8.2. Мне разрешено записывать только файлы реализации. (т. Е. Мне не разрешено добавлять функции into / ditch из файлов заголовков или main.)

В идеале, если объект класса имеет тип int, он будет печатать 2d-массив, который заполняется случайными целыми числами; если объект класса имеет тип float , он будет печатать 2d-массив, который заполняется случайными числами с плавающей запятой. До сих пор мне удавалось получать выходные данные 2D-массива, и результат кажется законным. Однако я продолжаю получать это исключение «0 [main] review3_cis17c_template_ 302 cygwin_exception::open_stackdumpfile: сброс трассировки стека в review3_cis17c_template_.exe.stackdump», которое, как я полагаю, связано с неправильным использованием ключа удаления в Table.h.

В чем причина проблемы? Я не смог найти ничего неправильного в моем механизме выделения памяти. Я опубликую свой Table.h, RowAray.h и main.cpp поскольку все они являются согласованными.

Вот мой RowAray.h:

 #ifndef ROWARAY_H
#define ROWARAY_H
#include<iostream>

template<class T>
class RowAray{
    protected:
        int size;
        T *rowData;
    public:
        RowAray(int);
        virtual ~RowAray();
        int getSize()const{return size;}
        T getData(int i)const{
            if(i>=0amp;amp;i<size)return rowData[i];
            else return 0;}
        void setData(int,T);
};

#include <cstdlib>

template<class T> 
RowAray<T>::RowAray(int r) {
    size = r;

    rowData = new T[r];

    for (int i = 0; i < r; i  ) {
        rowData[i] = static_cast<T>(rand() % 90   10);
    }
}

template<class T>
RowAray<T>::~RowAray() {
    delete []rowData;
}

template<class T>
void RowAray<T>::setData(int i, T value) {
    rowData[i] = value;
}
#endif /* ROWARAY_H */
  

Вот моя таблица.h:

 #ifndef TABLE_H
#define TABLE_H
#include "RowAray.h"

template<class T>
class Table{
    protected:
        int szRow;
        int szCol;
        RowAray<T> **columns;
    public:
        Table(unsigned int,unsigned int);
        Table(const Table<T> amp;);
        virtual ~Table();
        int getSzRow()const {return szRow;}
        int getSzCol()const {return szCol;}
        T getData(int,int)const;
        void setData(int,int,T);
        Table<T> operator (const Table<T> amp;);
};

template<class T>
Table<T>::Table(unsigned int r, unsigned int c) {
    szRow = r;
    szCol = c;

    columns = new RowAray<T>*[r];

    for(int i = 0; i < r; i  ) {
        columns[i] = new RowAray<T>(c);
    }
}

template<class T>
Table<T>::Table(const Table<T> amp;t) {
    szRow = t.getSzRow();
    szCol = t.getSzCol();

    columns = new RowAray<T>*[t.getSzRow()];

    for(int i = 0; i < t.getSzRow(); i  ) {
        columns[i] = new RowAray<T>(t.getSzCol());
    }

    for (int i = 0; i < t.getSzRow(); i  ) {
        for (int j = 0; j < t.getSzCol(); j  ) {
            columns[i]->setData(j, t.getData(i, j));
        }
    }
}

template<class T>
T Table<T>::getData(int r, int c) const {
    return columns[r]->getData(c);
}

template<class T>
Table<T>::~Table() {
    for (int i = 0; i < szRow; i  ) {
       delete []columns;
    }

    delete columns;
}

template<class T> 
Table<T> Table<T>::operator (const Table<T> amp;t) {
    Table<T> tab(t.getSzRow(), t.getSzCol());

    for(int i = 0; i < t.getSzRow(); i  ) {
        for (int j = 0; j <t.getSzCol(); j  ) {
            tab.columns[i]->setData(j, this->getData(i,j)   t.getData(i,j));
        }
    }

    return tab;
}
#endif /* TABLE_H */
  

И, наконец, мой main.cpp:

 #include <cstdlib>
#include <ctime>
#include <iostream>
#include <iomanip>
using namespace std;

//User Libraries
#include "Table.h"

//Global Constants

//Function Prototype
template<class T>
void prntRow(RowAray<T> *,int);
template<class T>
void prntTab(const Table<T> amp;);

//Execution Begins Here!
int main(int argc, char** argv) {
   //Initialize the random seed
   srand(static_cast<unsigned int>(time(0)));

   //Declare Variables
   int rows=3,cols=4;

   //Test out the Row with integers and floats
   RowAray<int> a(3);RowAray<float> b(4);
   cout<<"Test the Integer Row "<<endl;
   prntRow(amp;a,3);
   cout<<"Test the Float Row "<<endl;
   prntRow(amp;b,4);

   //Test out the Table with a float
   Table<float> tab1(rows,cols);
   Table<float> tab2(tab1);
   Table<float> tab3=tab1 tab2;

   cout<<"Float Table 1 size is [row,col] = ["
           <<rows<<","<<cols<<"]";
   prntTab(tab1);

   cout<<"Float Table 2 size is [row,col] = ["
           <<rows<<","<<cols<<"]";
   prntTab(tab2);

   cout<<"Float Table 3 size is [row,col] = Table 1   Table 2 ["
           <<rows<<","<<cols<<"]";
    prntTab(tab3);

   //Exit Stage Right
   return 0;
}

template<class T>
void prntRow(RowAray<T> *a,int perLine){
    cout<<fixed<<setprecision(1)<<showpoint<<endl;
    for(int i=0;i<a->getSize();i  ){
        cout<<a->getData(i)<<" ";
        if(i%perLine==(perLine-1))cout<<endl;
    }
    cout<<endl;
}

template<class T>
void prntTab(const Table<T> amp;a){
    cout<<fixed<<setprecision(1)<<showpoint<<endl;
    for(int row=0;row<a.getSzRow();row  ){
        for(int col=0;col<a.getSzCol();col  ){
            cout<<setw(8)<<a.getData(row,col);
        }
        cout<<endl;
    }
    cout<<endl;
}
  

Это моя первая публикация, поэтому я искренне извиняюсь, если коды неаккуратны. Любая помощь будет оценена!!

Комментарии:

1. Вы могли / должны были создать columns в Table классе a RowAray<RowAray<T>> вместо RowAray<T>** , что сокращает весь тот код, который у вас есть Table сейчас, который пытается выполнить динамическое выделение RowAray . Тогда все процедуры динамического выделения будут изолированы от RowAray класса, и там будут обнаружены любые ошибки.

2. Кроме того, вам RowAray необходимо реализовать определяемый пользователем конструктор копирования и оператор присваивания. Как только у вас эти две функции заработают должным образом, Table автоматически заработает (если вы использовали то, что я предложил в моем первом комментарии).

3. Но если вы хотите (или должны) сделать это сложным способом, держу пари, вы можете довольно быстро решить проблему с помощью интерфейса GDB, встроенного в Netbeans. Создайте отладочный исполняемый файл, запустите его в GDB через Netbeans, дождитесь сбоя и соберите информацию, когда отладчик остановится. Используйте собранную информацию, чтобы решить, где вы хотите искать дальше, поместите там breakpont, запустите программу снова. Продолжайте, пока проблема не будет решена.

4. Ваш Table деструктор выглядит странно: for (int i = 0; i < szRow; i ) {delete []columns;} . Что здесь удаляется? Вы удаляете одно и то же снова и снова в цикле. Но опять же, в этом нет необходимости, если вы делегировали все управление динамической памятью RowAray (что вам действительно следует сделать).

5. Кроме того, ваш RowAray<T>::getData возвращает 0, если размер выходит за рамки. Это сбивает с толку, поскольку нет никаких указаний на то, что индекс выходит за рамки, и если у вас было что-то вроде RowAray<std::string> , то преобразование в 0 отсутствует. Лучше просто выдать исключение, ничего не возвращая.