Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Проблемы с динамическим массивом внутри класса  (Прочитано 19883 раз)
0 Пользователей и 1 Гость смотрят эту тему.
romeo
Гость
« : 24-06-2008 08:30 » 

Вопрос в следующем - создаю  класс, экземпляры которого должны иметь длину задаваемую при вызове конструктора. Т.е. использую двумерный динамический массив. Если я описываю этот массив не с помощью класса, а в функции main, то ошибок не возникает, а если использую конструктор, то при инициализации массива возникает сообщение типа
Unhandled exception at 0x00401065 in myProg.exe: 0xC0000005: Access violation writing location 0xbaadf00d.
Вроде все проверил, не пойму где ошибка. Посмотрите пожалуйста
Код:
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <ctime>
//#include "Chromosome.h"

using namespace std;

class Chromosome
{
bool **Chromos;
int GeneQty, GeneSize;


public:
Chromosome (int GQty, int GSize);
~Chromosome();
void ShowChrom();

};


Chromosome::Chromosome (int GQty, int GSize)//создание пустой хромосомы, как массива генов
{
GeneQty = GQty; GeneSize = GSize;
Chromos = new bool* [GeneQty];
for (int i=0; i<GeneSize; i++)
{
Chromos[i] = new bool[GeneSize];
};
for (int l=0; l<GeneQty; l++)
       {
        for (int j=0; j<GeneSize; j++)   
   Chromos[l][j]= false;
       };
}

Chromosome::~Chromosome()
{
for(int i=0; i<GeneQty; i++)
delete [] Chromos[i];
delete [] Chromos;
}


void Chromosome::ShowChrom()
{
   cout<<"Cromosome "<<endl;
for (int i=0; i<GeneQty; i++)
    {
       for (int j=0; j<GeneSize; j++)   cout<<Chromos[i][j];
   cout<<"   ";
    }
cout<<endl;
};
void main()
{
int r=5, z=4;
Chromosome Ch1(r, z);
}
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #1 : 24-06-2008 09:06 » 

Ошибка - первый цикл должен до GeneQty работать, а не до GeneSize

for (int i=0; i<GeneSize; i++)

надо

for (int i=0; i<GeneQty; i++)


зы Ну и конечно конструктор в таком виде оставлять это просто безобразие, но я надеюсь ты это знаешь.
« Последнее редактирование: 24-06-2008 09:09 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
romeo
Гость
« Ответ #2 : 24-06-2008 09:09 » 

Ага,  я тоже заметил, но поздно. Все равно спасибо большое))
Записан
romeo
Гость
« Ответ #3 : 24-06-2008 09:11 » 

А вот по поводу конструктора я бы выслушал замечания . Так что если не трудно,  напиши
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #4 : 24-06-2008 09:24 » 

Улыбнуло
я бы сделал вектор векторов
Записан

Странно всё это....
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #5 : 24-06-2008 09:35 » 

Лучше поздно, чем после сдачи проекта. Ага

Насчёт улучшений... Если это ВСЁ, что происходит, то ничего не надо делать. Насчёт конструктора - я проглядел, я чёт решил, что это у тебя ф-я инициаллизации. Тогда надо было бы проверить уже существующую память и освободить её, если новый размер не совпадает с существующим. А если это у тебя единственный конструктор. То пойдёт. Я бы сделал стандартный конструктор и ф-ю инициаллизации. Ибо конструктор не возвращает значение. А значения ты будешь передавать разные. Но это уже просто совет по дизайну.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
romeo
Гость
« Ответ #6 : 24-06-2008 09:53 » 

Это не все, что происходит - это тот кусок где была проблема. Вообще я планирую, чтобы пользователь сразу выбрал размерность массива, а все экземпляры будут одного размера.
Тогда вопрос - можно ли сделать так, чтобы один раз передать в класс размерность массива и не указывать для каждого экземпляра одни и те же параметры?
Функция заполнения массива реализована отдельно, в конструкторе просто создается пустой массив с нулевыми (false) значениями.

ЗЫ: спасибо за комментарии
Записан
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 24-06-2008 10:36 » 

romeo, два варианта: статический массив или статический указатель.
Статический указатель (static) будет виден один и тот же во всех экземплярах класса - и ты сможешь всегда посмотреть, создавал уже или нет массив (указатель!=0).
Статические массив (int A[7777]) - инкапсулировать обычный массив в некую структуру, а экземпляр той структуры динамически создать в твоём классе (боремся с переполнением стека)
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #8 : 24-06-2008 11:59 » 

Я так и подумал, что это только нерабочая часть без всего лишнего.

Ну, статические переменные члены класса напрашиваются сами собой. Как Лёшка написал. Я бы только сделал статическими размерности - m_nGeneQty и m_nGeneSize и два конструктора. Честно говоря сразу не понял, что Лёшка имел ввиду. Ведь тебе нужны разные массивы с разным содержанием, но с одинаковой размерностью? Или? Но я думаю он пояснит.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #9 : 24-06-2008 12:12 » 

Или если важно отследить постоянство размерности, что я бы сделал так

Код:
class Chromosome
{
public:
Chromosome()
{
if( (0==m_nGeneQty)||(0==m_nGeneQty))
{
throw; // ещё пустые
}

                 // дальше по тексту

}

~Chromosome();

static void SetDim(int GQty, int GSize)
{
if( (0==m_nGeneQty)||(0==m_nGeneSize))
{
m_nGeneQty = GQty;
m_nGeneSize = GSize;
}
else
{
throw; // уже проинициаллизированы
}
}

private
bool **m_pChromos;
static int m_nGeneQty;
static int m_nGeneSize;

};

void main()
{
int r=5, z=4;
        Chromosome::SetDim(r,z)
Chromosome Ch1;
Chromosome Ch2;
Chromosome Ch3;
Chromosome Ch4;

...


Зы ну и везде, где они используются можно сначала проверку встроить.
« Последнее редактирование: 24-06-2008 12:14 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #10 : 24-06-2008 13:16 » 

пользуйтесь STL
хрень какая-то с памятью на куче. вы же при проблемах с выделением памяти, её в кучу вернуть не сможете нормально или сохраняйте при первом проходе данные о том инициализировали указатель во втором цикле или нет.

Вот интересно реально нужно данные на куче выделять или размер уже известен в CompileTime
Записан

Странно всё это....
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #11 : 24-06-2008 16:57 » 

Я так и подумал, что это только нерабочая часть без всего лишнего.

Ну, статические переменные члены класса напрашиваются сами собой. Как Лёшка написал. Я бы только сделал статическими размерности - m_nGeneQty и m_nGeneSize и два конструктора. Честно говоря сразу не понял, что Лёшка имел ввиду. Ведь тебе нужны разные массивы с разным содержанием, но с одинаковой размерностью? Или? Но я думаю он пояснит.


ну, человек просит
Цитата
чтобы один раз передать в класс размерность массива и не указывать для каждого экземпляра одни и те же параметры
вот я и предлагаю варианты ) Других, кстати, не вижу вариантов - либо динамический массив (один раз создаваемый) , либо статический (который на стеке нельзя создавать, ибо нефиг, поэтому толкаем в структуру - )

Код:
struct s_JustArray
{
enum
{
e_N=10000,
};

int* array;

s_JustArray()
{
array=new int [e_N];
if(array)memset(array,0,sizeof(*array)*e_N);
}

~s_JustArray()
{
if(array)
{
delete [] array;
}
}
//методы для работы с , если надо
//...
};

//рабочая структура
struct s_Work
{
static s_JustArray m_A;//получился динамический массив, который один на всех ))

};


LogRus, пусть человек в суть явления вникает, зачем ты его в шаблоны сразу толкаешь ? Которые нисколько не менее трудны для понимания
Записан

Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 24-06-2008 17:00 » 

а если всё же в каждом экземпляре нужен свой массив, тогда убираем static

Код:
//рабочая структура
struct s_Work
{
s_JustArray m_A;//массив в каждом экземпляре
};
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #13 : 24-06-2008 21:49 » 

Лёш, конечно каждой инстанции класса нужен будет свой массив. Вот я и не понял, как ты это с одним статическим массивом покрыть собрался. Ведь тогда он будет один для всех. Иного способа кроме как сделать статическую размерность я не вижу.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 25-06-2008 03:28 » 

виноват, исправлюсь ) Неравильно условие понял сначала
Записан

romeo
Гость
« Ответ #15 : 26-06-2008 16:52 » 

LogRus, старайся четче выражать свои мысли
Джон, спасибо)) ситуация проясняется. Ты правильно меня понял - для каждого экземпляра свой массив.
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #16 : 27-06-2008 03:33 » 

romeo, чего не понятного?
Код:
Chromos = new bool* [GeneQty];
for (int i=0; i<GeneSize; i++)
{
Chromos[i] = new bool[GeneSize];
};
если в цикле произойдёт исключение ты не сможешь вернуть память в кучу, т.к. не будешь знать выделял ты ей или нет. вектор безопасней.
Записан

Странно всё это....
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #17 : 27-06-2008 04:05 » 

LogRus, исключения там не будет, но, согласен, лучше проверять, выделилась ли память или вернулся нулевой указатель - а затем всё обратно удалить.
Но всё же ещё лучше выделить массив так:
Код:
Chromos = new bool [GeneQty*GeneSize];

и это всё становиться не менне удобно, чем пресловутый вехтор Улыбаюсь
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #18 : 27-06-2008 05:59 » 

Кидает, он кидает.
Сам попробуй.
Записан

Странно всё это....
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #19 : 27-06-2008 07:38 » 

как попробовать, как добиться такой ситуации:

1)была выделена память
2) при этом вылетело исключение

?
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #20 : 27-06-2008 11:33 » 

попробуй в цикле выделять по сотнями мегабайт память и ловить при этом  std::bad_alloc
и у видишь что он ловится Улыбаюсь
сам специально проверил
летит исключение и стандарт читал
там сказано new ()[] throw(std::bad_alloc)
Записан

Странно всё это....
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 27-06-2008 12:32 » 

LogRus, во первых, я предлагаю одним блоком выделить, а не серией. Тут - либо выделилось , либо нет, никакой потери. Если не выделилось = вернёт 0

а при чём тут std:: ? Улыбаюсь Оно точно сюда ?
Проверю дома, сейчас нельзя компутер ронять  - сижу глыбоко в отладкке Улыбаюсь
Записан

romeo
Гость
« Ответ #22 : 28-06-2008 08:07 » 

LogRus, а почему вектор безопаснее? какая разница каким способом память выделить? просвети пожалуйста
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #23 : 28-06-2008 08:22 » 

romeo, STL вектор давно проверенный рабочий класс. При сохранении там массивов не нужно в последствии задумываться об уничтожении вовремя выделенной памяти. При уничтожении вектора, вся память автоматически возрашается системе. Хотя, если принимать правила предосторожности, то можно обойтись и без него. Но это будет чуть больше работа ручками и головой.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
romeo
Гость
« Ответ #24 : 28-06-2008 08:27 » 

Finch, а что, тот деструктор, который я прописал (см. листинг вверху) разве не гарантирует возврата памяти системе?
Записан
romeo
Гость
« Ответ #25 : 28-06-2008 08:49 » 

Джон, еще вопросик, что за условие в 9-м посте
Код:
if( (0==m_nGeneQty)||(0==m_nGeneSize))
?
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #26 : 28-06-2008 09:06 » 

Кстати у тебя в деструкторе тоже затисалась ошибка, что и в конструкторе. Я как раз об этом, когда говорил
Цитата
Хотя, если принимать правила предосторожности, то можно обойтись и без него. Но это будет чуть больше работа ручками и головой.

Цитата
Джон, еще вопросик, что за условие в 9-м посте
Код:

 if( (0==m_nGeneQty)||(0==m_nGeneSize))

?
Это проверка на нуль одного из параметров.
« Последнее редактирование: 28-06-2008 09:12 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
romeo
Гость
« Ответ #27 : 28-06-2008 09:19 » 

Это-то да, я у себя потом исправил, а правильный листинг не выложил. Тем не менее деструктор типа
Код:
Chromosome::~Chromosome()
{
for(int i=0; i<GeneSize; i++)
delete [] Chromos[i];
delete [] Chromos;

}
не гарантирует отсутствие проблем с высвобождением памяти?
Записан
romeo
Гость
« Ответ #28 : 28-06-2008 09:22 » 

А возможно ли создать статический массив экземпляров класса, если конструктор при этом имеет входные параметры?
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #29 : 28-06-2008 09:25 » 

Он то освободит, насколько я знаю, по стандарту при попытке удаления адресса ֳֹNULL, оператор delete не должен предпринимать каких либо действий или исключений.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines