Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / проблемы с последовательностью вызовов десктрукторов / 22 сообщений из 22, страница 1 из 1
18.10.2005, 14:47
    #33330608
geltr
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
Прошу поразмышлять над такой проблемой. Есть класс, реализующий очередь в самом общем виде, т.е. подходящий для любых типов элементов, образующих очередь. Также есть, например, класс 'C'-строк, содержащий указатель на строку. Для этого указателя память выделяется динамически в зависимости от длины строки. Проблема такова: в клиентском файле, реализующем работу с очередью из строк, при создании объектов-строк и помещении их в очередь при завершении программы, необходим сначала вызов деструктора для класса строк, а затем уже вызов деструктор для самой очереди. При не соблюдении данной очередности вызовов деструкторов возникает ошибка во время исполнения программы. Как можно решить эту проблемму, не прибегая к наследованию и другим усложнениям.
...
Рейтинг: 0 / 0
18.10.2005, 14:57
    #33330661
redskin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
В чем именно проблема?
Есть контейнер (пусть очередь в данном случае, хотя не важно)
Вполне естественно, если при уничтожении сначала отработают деструкторы для элементов контейнера, а потом деструктор самого контейнера. Так IMHO и должно работаь. В чем может быть засада? Или я чего-то недопонял в вопросе?
...
Рейтинг: 0 / 0
18.10.2005, 16:05
    #33330990
geltr
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
redskinВ чем именно проблема?
? Или я чего-то недопонял в вопросе?

Напишу конкретней:
int main()

{

создание объекта очереди;
заполнение очереди объектами-строками;

} - здесь программа заканчивается; очередь уничтожается, не успев высвободить выделенную память для объектов-строк. Т.е. деструктор для строк не вызывается перед деструктором для очереди. (деструктор объектом не вызовешь!).
...
Рейтинг: 0 / 0
18.10.2005, 16:10
    #33331006
Сергей Ильич
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
geltr redskinВ чем именно проблема?
? Или я чего-то недопонял в вопросе?

Напишу конкретней:
int main()

{

создание объекта очереди;
заполнение очереди объектами-строками;

} - здесь программа заканчивается; очередь уничтожается, не успев высвободить выделенную память для объектов-строк. Т.е. деструктор для строк не вызывается перед деструктором для очереди. (деструктор объектом не вызовешь!).
std::vector< std::string > корректно все делает. Что мешает сделать так же?
...
Рейтинг: 0 / 0
18.10.2005, 16:19
    #33331027
geltr
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
Сергей ИльичЧто мешает сделать так же?

Просто необходимо написать самому очередь из C-строк без использования "встроенных" классов С++. Т.е. написать класс 'очередь' и класс 'строка', являющийся элементами очереди. Программа работает, но выдает ошибку во время выполнения.
...
Рейтинг: 0 / 0
18.10.2005, 16:21
    #33331034
Gluk (Kazan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
...
Рейтинг: 0 / 0
18.10.2005, 16:21
    #33331038
Gluk (Kazan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
В C нет строк
...
Рейтинг: 0 / 0
18.10.2005, 16:28
    #33331056
geltr
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
Gluk (Kazan)В C нет строк
Я знаю, поэтому и пишу "C-строки", что означает массив char'ов, завершенный '\0'.
...
Рейтинг: 0 / 0
18.10.2005, 16:35
    #33331085
geltr
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
Gluk (Kazan) Если речь идет об указателях на объекты в очереди
Слишком сложно. Мне необходима самая простая реализация без шаблонов и без _ptr, потому что я пока их просто не знаю.
...
Рейтинг: 0 / 0
18.10.2005, 16:56
    #33331174
funikovyuri
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
что-то вы не то рассказываете! Приведите код
...
Рейтинг: 0 / 0
18.10.2005, 17:04
    #33331209
Gluk (Kazan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
Ну дык и вызывай delete явно, что мешает ???
А вобче, учи C++
...
Рейтинг: 0 / 0
18.10.2005, 17:55
    #33331387
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
geltrКак можно решить эту проблемму, не прибегая к наследованию и другим усложнениям.
В конце работы пробежать в цикле по всей очереди и освободить память выделеную для каждого из элементов. Все.
Кстати, то что называешь "С-строки" обычно называется ASCIIz строки :)
...
Рейтинг: 0 / 0
18.10.2005, 18:32
    #33331498
geltr
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
funikovyuriчто-то вы не то рассказываете! Приведите код

Так и быть. Привожу код программы.
...
Рейтинг: 0 / 0
18.10.2005, 18:48
    #33331541
redskin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
geltr funikovyuriчто-то вы не то рассказываете! Приведите код

Так и быть. Привожу код программы.


Эээ.... так нельзя.
Такой класс строки, который у вас написан, никуда не годится.
Я даже не стал смотреть на реализацию очереди, поэтму не скажу точную причину ваших граблей, но помедитируйте вот этим примером: (класс C_string - из вашего исходника)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
#include <iostream>

using namespace std;

class C_string
{
private:
	char * pstr;
public:
	C_string(char * ps = "none");
	~C_string() { delete [] pstr; }
	char * str() { return pstr; }
};

C_string::C_string(char * ps)
{
	pstr = new char[strlen(ps) +  1 ];
	strcpy(pstr,ps);
}

void f(C_string c_str)
{
	cout << c_str.str();
}

int main(int argc, char *argv[])
{

	{
		C_string c("abc");
		f(c);
	}

	return  0 ;
}

Тестовая "нехорошая" функция моя.
И не говорите, что у вас никогда такого не случится и что ваш класс все будут использовать "как надо". :-))

p.s. кстати, как раз такую задачку (почему все компилируется, но валится) дают в нашем отделе на собеседовании. Азы С++.
...
Рейтинг: 0 / 0
18.10.2005, 19:10
    #33331578
redskin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
p.s. Hint: добавьте в описание класса (из целого примера, который вы прикрепили к сообщению) такую строчку:

Код: plaintext
1.
2.
public:
  C_string& operator=(const C_string& str){cout << "operator =\n"; return *this;} ;

Запустите на выполнение и посмотрите на вывод.
...
Рейтинг: 0 / 0
19.10.2005, 06:19
    #33331964
Kornjushin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
p.s. кстати, как раз такую задачку (почему все компилируется, но валится) дают в нашем отделе на собеседовании. Азы С++.

А можно не сильно сведущим ответить что не так с этим классом, глюк на лицо, но что не так не пойму
...
Рейтинг: 0 / 0
19.10.2005, 08:28
    #33332039
redskin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
Kornjushin
А можно не сильно сведущим ответить что не так с этим классом, глюк на лицо, но что не так не пойму

Один из членов класса C_string - указатель pstr. На конструкторе выделяется память, на деструкторе освобождается, вроде бы все в порядке. Но для C_string не опеределены ни конструктор копирования, ни оператор присваивания. В этом случае компилятор генерирует их самостоятельно и в них выполняется обычное побитовое копирование один в один.

Теперь при попытке присвоить один объект класса C_string другому или передать его по значению в функцию, будет создана абсолютно идентичная копия. Адрес в pstr тоже будет одинаковым. Когда объектам придет время умирать, будет попытка дважды освободить одну и ту же область памяти и привет.

Выход: либо нормально реализовать копирующий конструктор и оператор присваивания, либо явно запретить копирование и передачу объектов по значению, поместив объявления этих методов в private и не определяя их.
...
Рейтинг: 0 / 0
19.10.2005, 10:08
    #33332235
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
Это как-то странно. Если очередь ответствена за удаление своих элементов, то она должна сначала удалить все элементы очереди (стороки) а потом уже себя. По другому и быть не может, если не предпринимать дополнительных усилий.
...
Рейтинг: 0 / 0
19.10.2005, 10:40
    #33332348
Kornjushin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
А показать как это реализовать не затруднит?
...
Рейтинг: 0 / 0
19.10.2005, 11:22
    #33332488
redskin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
KornjushinА показать как это реализовать не затруднит?

Явный запрет копирования и передачи по значению:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
...
class C_string
{
private:
	C_string(const C_string&);
	C_string& operator=(const C_string&);

...


При этом сами методы не определяем. Если мы потом где-нибудь попробуем создать копию объекта, то компилер грязно выругается. А можно их перенести таки в public и реализовать, например так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
#include <iostream>
using namespace std;

class C_string
{
private:
	char * pstr;

public:
	C_string(char * ps = "none");
	~C_string() { delete [] pstr; }

	C_string(const C_string&);
	C_string& operator=(const C_string&);

	char * str() const { return pstr; };
};

C_string::C_string(char * ps)
{
	pstr = new char[strlen(ps) +  1 ];
	strcpy(pstr,ps);
}

C_string::C_string(const C_string& c)
{
	pstr = new char[strlen(c.str()) +  1 ];
	strcpy(pstr, c.str());
}
C_string& C_string::operator=(const C_string& c)
{
	if(this != &c)
	{
		delete[] pstr;
		pstr = new char[strlen(c.str()) +  1 ];
		strcpy(pstr, c.str());
	}
	return *this;
}

void f(C_string c_str)
{
	cout << c_str.str() << endl;;
}

int main()
{
	C_string c1, c2, c3("abc");
	c1 = c3;
	f(c1);
	f(c2);
	f(c3);

	return  0 ;
}

Вообще эта тема обстоятельно разжевана во многих хороших книгах по С++ (Эккель, Майерс и пр.)
...
Рейтинг: 0 / 0
19.10.2005, 16:15
    #33333494
geltr
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
Всем спасибо за активное обсуждение, особенно redskin'у.
...
Рейтинг: 0 / 0
19.10.2005, 16:59
    #33333632
kolobok0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
проблемы с последовательностью вызовов десктрукторов
geltrВсем спасибо за активное обсуждение....

добавлю, что на мой взгляд Вам будет интересно почитать Джэфа Элджэра...

в этой помойке найдёте электронный вариант...

С++ . Библиотека программиста. Автор: Джефф Элджер. 259 стр., РУС, PDF.


с уважением
(круглый)
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / проблемы с последовательностью вызовов десктрукторов / 22 сообщений из 22, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]