Неверный размер размещения (в конструкторе копирования производного класса) - PullRequest
1 голос
/ 17 марта 2012

Я сузил свою проблему до конструктора копирования производных классов, но я не уверен в причине. РЕДАКТИРОВАТЬ: M, N и данные являются частными.Я получаю сообщение об ошибке «Недопустимый размер выделения: 4294967295 байт», которое, как я понимаю, вызывается при передаче значения -1 новому.Я не уверен, почему это произойдет, если данные не будут потеряны, когда класс comunicate.

BinaryMatrix::BinaryMatrix(const BinaryMatrix& copy) : Matrix(copy)
{
    //cout << "Copy Constructor\n";

    M = copy.M;
    N = copy.N;

    data = new double[M*N]; //This line causes the allocation error

    for (int i = 0; i < M; i++)
    {
            for (int j = 0; j < N; j++)
            {
                    data[i*N+j] = copy.data[i*N+j];
            }
    }
}

Выше приведен мой производный конструктор копирования, который вызывает ошибку.Я пометил линию выделения.

Я могу только предположить, что M и N читаются неправильно.Хотя я не уверен почему.Я включу как производные, так и базовые конструкторы, а также базовую копию.

Спасибо за любую помощь.

КОНСТРУКТОР МАТРИЦЫ (БАЗЫ)

Matrix::Matrix(int M, int N, double* input_data)
{
    this->M = M;
    this->N = N;

    //cout << "Matrix Constructor\n";
    data = new double[M*N];

    for (int i = 0; i < M; i++)
    {
            for (int j = 0; j < N; j++)
            {
                    data[i*N+j] = input_data[i*N+j];
            }
    }

    delete [] input_data;
}

КОНСТРУКТОР КОПИРОВАНИЯ МАТРИЦЫ (БАЗЫ)

Matrix::Matrix(const Matrix& copy)
{
    //cout << "Copy Constructor\n";

    M = copy.M;
    N = copy.N;

    data = new double[M*N];

    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        {
            data[i*N+j] = copy.data[i*N+j];
        }
    }
}

КОНСТРУКТОР БИНАРИЙНОГО (ПРОИЗВОДНОГО)

BinaryMatrix::BinaryMatrix(int M, int N, double* input_data) : Matrix(M, N, input_data)
{
    data = new double[M*N];

    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        {
            this->data[i*N+j] = this->getRead(i, j);
        }
    }

    double thr_val = this->Mean();

    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        {
            if (this->data[i*N+j] > thr_val)
                this->data[i*N+j] = 1;

            if (this->data[i*N+j] < thr_val)
                this->data[i*N+j] = 0;
        }
    }
}

Ответы [ 3 ]

1 голос
/ 17 марта 2012

Почему вы создаете новую копию данных матрицы в конструкторе копирования BinaryMatrix?Конструктор копирования Matrix, который вы вызываете из конструктора копирования BinaryMatrix, уже делает это.

В конструкторе копирования BinaryMatrix вы отбрасываете копию матричных данных уже созданного Matrix конструктора копирования (без delete его создания) и создаете новый.Это утечка памяти - память будет исчерпана, если вы будете делать это достаточно часто.

0 голосов
/ 17 марта 2012

Если M и N являются частными для Matrix, а BinaryMatrix происходит от Matrix, я не уверен, почему ваш код компилируется (у вас не должно быть доступа к M, N в BinaryMatrix).Если ваша декларация BinaryMatrix также включает членов M и N (а также Matrix::N и Matrix::M), то это может быть источником проблемы.

Если BinaryMatrix нене объявляйте M и N, тогда я думаю, что у нас все еще недостаточно данных для диагностики вашей проблемы.Чтобы немного догадаться, возможно, M * N не вписывается в тип, используемый для M. Таким образом, у вас есть арифметическое переполнение.Размер массива указан в size_t, поэтому приведение будет работать нормально.

Кроме того, вы, вероятно, хотите делегировать управление данными точно одному из классов.То есть, сделайте это:

BinaryMatrix::BinaryMatrix(const BinaryMatrix& copy) : Matrix(copy)
{
    // M, N, data already set in Matrix::Matrix(const Matrix&)
    // The data has also been copied, so there is nothing to do here.
}

или это:

#include <algorithm>

BinaryMatrix::BinaryMatrix(const BinaryMatrix& copy) 
 : Matrix(), M(0), N(0), 
   data(0) // null in case new throws an exception (avoid bad delete in dtor).
{
    const size_t nelems(size_t(copy.M)*size_t(copy.N));
    data = new double[nelems];
    M = copy.M;
    N = copy.N;
    stl::copy(copy.data, copy.data+nelems, data);
}

Я думаю, что в общем случае не рекомендуется использовать int для итерации динамических структур данных, посколькуничто не гарантирует, что фактический размер структуры вписывается в int.Однако эта гарантия существует для size_t (любой существующий объект должен иметь размер, представляемый в size_t, поэтому вы можете перебирать любой смежный объект, используя size_t).

На самом деле я недействительно уверен, какое различие (цели или поведения) вы пытаетесь получить от Matrix и BinaryMatrix.Данные, похоже, имеют одинаковое представление.Если это различие в поведении, а не в представлении, которое вы ищете, я думаю, что было бы лучше использовать композицию (то есть, отдельный не наследуемый класс представления), а не наследование.См. Что такое принцип подстановки Лискова? для объяснения того, как полезно думать о том, когда использовать наследование.

Однако, если ни один из ответов, которые вы видели до сих пор, на самом деле не помогает решитьваша проблема, вы должны уделить некоторое время сокращению вашего примера: какая самая маленькая полная программа-пример, которая демонстрирует вашу проблему?Опубликовать это.

0 голосов
/ 17 марта 2012

Если ошибка в том, что M и N являются частными. тогда вы должны изменить там уровень защиты на защищенный или общедоступный или предоставить метод доступа, который есть. Vairables, определенные в базовом классе, которые являются частными, недоступны для производных классов.

class A
{
    int x;
}

class B : public A
{
    int DoSomething()
    { 
        return x; //This is an error X is private to class A and as such inaccessible. 
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...