imho.ws
IMHO.WS  

Вернуться   IMHO.WS > Компьютеры > Программирование
Опции темы
Старый 29.01.2006, 02:22     # 1
Crazy_kettle
Junior Member
 
Регистрация: 13.05.2004
Сообщения: 128

Crazy_kettle Известность не заставит себя ждатьCrazy_kettle Известность не заставит себя ждать
std::vector

возникли у меня проблемы с использованием класса vector из стандатрной библиотеки.
Компилятор MS Visual Studio .Net при выполнении следующего фрагмента:
Код:
#include <stdlib.h>
#include <iostream>
#include <conio.h>

using std::vector;
using std::cout;
using std::endl;

struct TS{
	char* str;
	int len;
	TS():str(0),len(0){}
	~TS(){
		free(str);
		str=0;
	}
};
int main(){
	TS s;	
	vector<TS> vec;
	char* temp="This is string";
	s.len=strlen(temp);
	s.str=static_cast<char*>(malloc(s.len+1));
	strcpy(s.str,temp);
	cout<<s.str<<'\n';
	vec.push_back(s);
	cout<<(s.str==0)<<'\t'<<s.str<<'\n';
	TS& el=vec.back();
	cout<<(el.str==s.str)<<'\t'<<el.str<<endl;
	s.str=0;//Чтобы деструктор не пытался освободить память повторно.
	return 0;
}
выдаёт (к тому же возникает какая-то ошибка):
Код:
This is string
0       8RD
1       8RD
Причём, если убрать из структуры TS дескриптор, то выполняется на ура.
Только вот не пойму, причём здесь деструктор может быть причастен, ведь переменная s и вектор vec ещё используются (не говоря уже об области видимости)? Более того, как для переменной s, так и для vec.back(), он явно не вызывался, т.к. s.str==vec.back().str!=0.
Может, у кого идеи есть по поводу этой проблемы.

P.s. Такая "ботва" была обнаружена при отладке написанной программы, где такой подход был использован для того, чтобы при вызове vec.clear() автоматически освобождалась занятая память и при этом избежать "ненужных" выделений памяти и копирования. Вопрос 2: Что делать? Изменять char* на string не хочется, ибо нужно будет очень много править (везде идёт работа с C-строками). Конечно, можно, убрать деструктор и перед вызовом vec.clear() производить "чистку" или ввести новый класс
Код:
class myvector: public vector<TS>{
public:
	void clear(){
		for (int i=0;i<size();i++)
			free((*this)[i].str);
		vector<TS>::clear();
	}
};
Может у вас есть более изящные предложения?

Последний раз редактировалось Crazy_kettle; 29.01.2006 в 22:55.
Crazy_kettle вне форума  
Старый 29.01.2006, 09:27     # 2
Drakosha
Full Member
 
Аватар для Drakosha
 
Регистрация: 16.10.2002
Адрес: ArchLinux, Internet
Сообщения: 557

Drakosha Реально крут(а)Drakosha Реально крут(а)Drakosha Реально крут(а)Drakosha Реально крут(а)
Во первых, на g++ 3.4.4 всё пашет
Во вторых, если где-то создаётся временный объект TS, например при выполенении этой строчки: vec.push_back(s); то деструктор может быть вызван им. Поэтомы для объектов с поинтерами всегда стоит писать operator= и copy constructor. Если написать их в private без имплементации, т.е. запретить, то компилятор даст ошибку в том месте где он хотел их использовать.
В третьих, лучше пользоваться new и delete т.к. они вызывают контруктор/деструктор в отличии от malloc/free. В этом примере это не важно imho.

Надеюсь помог

Последний раз редактировалось Drakosha; 29.01.2006 в 09:40.
Drakosha вне форума  
Старый 29.01.2006, 21:47     # 3
alexey_ma
Member
 
Регистрация: 10.03.2002
Адрес: Israel
Сообщения: 245

alexey_ma Нимб уже пробиваетсяalexey_ma Нимб уже пробивается
2 Drakosha.
vec.push_back(s) не создает стековый обьект. push_back в параметре получает константный референс
Код:
void push_back(
   const Type& _Val
);
Именно поэтому и происходит креш, вектор при добавлении элемента плоско копирует структуру. Получается две структуры имееющие указатель на один и тот -же адрес. Это христоматийная ошибка. На таких примерах обычно показывают зачем нужен копи-конструктор. Обьекты помещаемые в стандартные (stl) контейнеры должны иметь копи-конструкторы.


2 Crazy_kettle.
Что-то намешано у тебя и С и С++.
Вектор на самом деле при удалении элемента вызывет для него деструктор.
Попробуй хранить в векторе указатели на структуру TS, а не сами сами структуры, тогда сам сможешь управлять выделением и освобожденим пямяти. То есть что то типа
Код:
struct TS{
	char* str;
	int len;
	TS():str(0),len(0){}
	TS(const char* s) ///нормальный конструктор 
	{
		len = strlen(s);
		str= new char[len+1];
		strcpy(str,s);
	}
	~TS(){
		if(str) 
			delete [] str;
		str=0;
	}
};

int main ()
{
	vector<TS*> vec;
	///Это слишком длинно/////////
	TS* pTS = new TS();//("This is string");
	char* temp="This is string";
	pTS->len = strlen(temp);
	pTS->str = new char [pTS->len+1];
	strcpy(pTS->str,temp);
	/////Проще написать нормальный конструктор и сделать 
	/////так     TS* pTS = new TS("This is string");
	cout<<pTS->str<<'\n';
	vec.push_back(pTS);
	cout<<(pTS->str==0)<<'\t'<<pTS->str<<'\n';
	//запомнить указатель 
	TS* pTS1 = vec.back();
	cout<<(pTS1->str==pTS->str)<<'\t'<<pTS1->str<<endl;
	///освобождение пямяти////////////
	//удалить указатель из вектора 
	vec.pop_back(); /// еще можно так  vec.erase(0) или vec.clear();
	//удалить сам указатель
	delete pTS1 ;

}
__________________
Best Regards

Последний раз редактировалось alexey_ma; 29.01.2006 в 22:06.
alexey_ma вне форума  
Старый 29.01.2006, 22:54     # 4
Crazy_kettle
Junior Member
 
Регистрация: 13.05.2004
Сообщения: 128

Crazy_kettle Известность не заставит себя ждатьCrazy_kettle Известность не заставит себя ждать
Цитата:
Сообщение от alexey_ma
Что-то намешано у тебя и С и С++.
Пишу как умею . Начал недавно переходить с С на С++. С бинарными файлами на С++ я не работал ещё, поэтому решил изпользовать стандартную библиотеку С (чтобы не тратить лишнее время на поиск множества багов, кот. всегда выскакивают, когда начинаешь что-то изучать).
Цитата:
Сообщение от alexey_ma
Именно поэтому и происходит креш, вектор при добавлении элемента плоско копирует структуру. Получается две структуры имееющие указатель на один и тот -же адрес. Это христоматийная ошибка.
Ошибка будет, если изменять строку и из вектора и из структуры, а если нет, то какая тут ошибка?
В проге структура используется только для инициализации и чтобы запихнуться в вектор.

Цитата:
Сообщение от alexey_ma
Вектор на самом деле при удалении элемента вызывет для него деструктор.
Для этого деструктор и писался . В первом посте это и написано. Проблема, только что нигде перед использованием НЕ удаляются элементы из вектора и как было также написано деструкторы элементов НЕ вызывались.
Цитата:
Сообщение от Drakosha
Во первых, на g++ 3.4.4 всё пашет
Во вторых, если где-то создаётся временный объект TS, например при выполенении этой строчки: vec.push_back(s); то деструктор может быть вызван им.
Да похоже программисты Microsoft что-то с STL перемудрили и действительно где-то у них создаётся временный объект. Хотя это мне кажется странным, т.к. для больших объектов из-за этого скорость должна сильно упасть!!!!!!
Цитата:
Сообщение от Drakosha
Поэтому для объектов с поинтерами всегда стоит писать operator= и copy constructor.
Дело в том, что писать их не хотелось, ибо каждая такая операция медленная и причём НЕнужная (Имхо).
З.Ы. Как я понял, изящней последнего решения (то, кот. с наследованием) в моём первом после ничего не придумано. Его я и реализовал.

Последний раз редактировалось Crazy_kettle; 29.01.2006 в 23:03.
Crazy_kettle вне форума  
Старый 30.01.2006, 11:13     # 5
Drakosha
Full Member
 
Аватар для Drakosha
 
Регистрация: 16.10.2002
Адрес: ArchLinux, Internet
Сообщения: 557

Drakosha Реально крут(а)Drakosha Реально крут(а)Drakosha Реально крут(а)Drakosha Реально крут(а)
Цитата:
alexey_ma:
2 Drakosha.
vec.push_back(s) не создает стековый обьект. push_back в параметре получает константный референс
Согласен частично. Т.е. во время передач в функцию временый обьект не создаётся. Но неизвестно какая там имплементация, всё таки где-то он копируется . Кстати, в gcc не копируется :D
Цитата:
Crazy_kettle:
Да похоже программисты Microsoft что-то с STL перемудрили и действительно где-то у них создаётся временный объект. Хотя это мне кажется странным, т.к. для больших объектов из-за этого скорость должна сильно упасть!!!!!!
Цитата:
Crazy_kettle:
100% согласен
Дело в том, что писать их не хотелось, ибо каждая такая операция медленная и причём НЕнужная (Имхо).
З.Ы. Как я понял, изящней последнего решения (то, кот. с наследованием) в моём первом после ничего не придумано. Его я и реализовал.
Во первых, copy constructor и operator= всегда стоит написать или запретить. (Пользоваться дефолтным === написать)
Бо вторых, по моему правильное решение написать их все таки так как твоэ решени может упасть на каком-то другом сценарии - все так там возможна двойная деаллокация.
Drakosha вне форума  
Старый 30.01.2006, 12:22     # 6
alexey_ma
Member
 
Регистрация: 10.03.2002
Адрес: Israel
Сообщения: 245

alexey_ma Нимб уже пробиваетсяalexey_ma Нимб уже пробивается
Цитата:
Crazy_kettle:
Да похоже программисты Microsoft что-то с STL перемудрили и действительно где-то у них создаётся временный объект. Хотя это мне кажется странным, т.к. для больших объектов из-за этого скорость должна сильно упасть!!!!!!
Ничего тут мудрого нет. Повторяю еще раз медленно. Ты создал структуру (назовем его ts), при попытке добавления это структуры в в вектор создается новый обьект (назовем его ts1) , в ts1 копируется ts. Поскольку копи-конструктора у тебя нет, то копируется плоско - тоесть ПОБАЙТНО. В итоге получаем две структуры содержащие указатель на одну и ту-же область памяти. Для обеих структур вызывается деструктор (не обязательно при удалении из вектора, у тебя просто обьекты выходят из скопа, то есть кончается их время жизни) и пытается дважды освободить один и тот же указатель. В итоге креш. Я же писал Обьекты помещаемые в стандартные (stl) контейнеры должны иметь копи-конструкторы. . Не надо косить на Microsoft, лучше изучи как работать с STL. Это давно уже стандарт языка С++. И писать надо не как умею , а как того требуют правила языка. Не стыдно быть чайником - стыдно им оставаться.

Цитата:
Drakosha
Но неизвестно какая там имплементация, всё таки где-то он копируется
Еще как известно. STL - это библиотека шаблонов и поставляется в исходниках
__________________
Best Regards
alexey_ma вне форума  
Старый 30.01.2006, 13:24     # 7
PSyton
Junior Member
 
Аватар для PSyton
 
Регистрация: 19.04.2002
Адрес: Дом
Пол: Male
Сообщения: 187

PSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форуме
Цитата:
Сообщение от Crazy_kettle
Пишу как умею . Начал недавно переходить с С на С++. С бинарными файлами на С++ я не работал ещё, поэтому решил изпользовать стандартную библиотеку С (чтобы не тратить лишнее время на поиск множества багов, кот. всегда выскакивают, когда начинаешь что-то изучать).
...
Да похоже программисты Microsoft что-то с STL перемудрили и действительно где-то у них создаётся временный объект. Хотя это мне кажется странным, т.к. для больших объектов из-за этого скорость должна сильно упасть!!!!!!
Прошу прощения за повтор, но все же...
Уважаемый, MS тут не причем. STL он и в Африке STL. И в доках четко и ясно написано что конструкторы копирования и операция присваивания для пользовательских классов при хранении их не по указателю необходимы.
__________________
Дураки не динозавры - они не вымрут...

Последний раз редактировалось PSyton; 30.01.2006 в 13:32.
PSyton вне форума  
Старый 30.01.2006, 20:00     # 8
Crazy_kettle
Junior Member
 
Регистрация: 13.05.2004
Сообщения: 128

Crazy_kettle Известность не заставит себя ждатьCrazy_kettle Известность не заставит себя ждать
Цитата:
Сообщение от Drakosha
Во первых, copy constructor и operator= всегда стоит написать или запретить. (Пользоваться дефолтным === написать)
Если запретить, то имхо в вектор ничего нельзя будет добавить . Кстати, Имхо вызов конструктора не вредит. Другое дело деструктор, но его я убрал . Память освобождается при очистке вектора. Да это решение не идеально, т.к. нужно иметь ввиду возможные кросс-референсы и memory-leaks (при использовании комманд копирования и изменения вектора, отличной от clear). Но это на данный момент не используется! Более того, написав copy constructor и operator=, я потеряю в скорости, т.к. будет происходить как минимум 2 НЕ ОБЯЗАТЕЛЬНЫХ копирований строки (от одного можно избавиться, но не от второго ).
[hr]
Цитата:
Сообщение от alexey_ma
Ты создал структуру (назовем его ts), при попытке добавления это структуры в в вектор создается новый обьект (назовем его ts1) , в ts1 копируется ts. Поскольку копи-конструктора у тебя нет, то копируется плоско - тоесть ПОБАЙТНО. В итоге получаем две структуры содержащие указатель на одну и ту-же область памяти. Для обеих структур вызывается деструктор (не обязательно при удалении из вектора, у тебя просто обьекты выходят из скопа, то есть кончается их время жизни) и пытается дважды освободить один и тот же указатель. В итоге креш.
Ну это я знаю и имею ввиду. Только, кажется, ваше объяснение НЕ подходит. Я же писал:
Цитата:
Сообщение от Crazy_kettle
переменная s и вектор vec ещё используются (не говоря уже об области видимости)
Цитата:
Сообщение от Crazy_kettle
Более того, как для переменной s, так и для vec.back(), он(деструктор) явно не вызывался, т.к. s.str==vec.back().str!=0.
Более того, ту возможность, о которой вы писали, я предусмотрел:
Цитата:
Сообщение от Crazy_kettle
s.str=0;//Чтобы деструктор не пытался освободить память повторно.
Да при окончании программы вызывается деструктор для строки. Но т.к. s.str==NULL, то ф-ция free(s.str) НИЧЕГО не делает, а, значит, можно считать, что для структуры s деструктор вовсе отсутствует .
Не предусмотрел я то, что при реализации vector:ush_back может создаваться временный объект (что вы категорически отрицаете) и для него вызываться деструктор, который всё портит. Я не виню за это программистов Microsoft, это их дело как писать свои процедуры.
Цитата:
Сообщение от alexey_ma
И писать надо не как умею, а как того требуют правила языка. Не стыдно быть чайником - стыдно им оставаться.
Почему-то мне, кажется, что изучать новые средства лучше на простеньких программках. Т.к. в нормальных возможны большие проблемы с отладкой, из-за чего получается «кривой» код (т.к. переписывать с нуля влом).
[hr]
Цитата:
Сообщение от Crazy_kettle
Да похоже программисты Microsoft что-то с STL перемудрили и действительно где-то у них создаётся временный объект. Хотя это мне кажется странным, т.к. для больших объектов из-за этого скорость должна сильно упасть!!!!!!
Цитата:
Сообщение от PSyton
Уважаемый, MS тут не причем. STL он и в Африке STL.
Кажется, Вы меня не правильно поняли. Я не скидываю свою вину по написанию неправильного кода на программистов MS. Пусть пишут как хотят, как умеют, и как думают они (не я). Да у меня был баг и я его поправил.
Интересует меня другое. Я ведь всегда думал, что STL разрабатывалась/писалась так, чтобы обеспечивать максимальное быстродействие. Только вот зачем нужно создавать временный объект? (конечно, программистам MS виднее, но разработчики библиотеки, поставляемой с g++ 3.4.4, обошлись же без этого). И это, имхо, создание временного объекта может отнимать уйму времени (если этот объект очень большой). Не зря же объекты передаются по ссылке ?!
Crazy_kettle вне форума  
Старый 30.01.2006, 22:54     # 9
alexey_ma
Member
 
Регистрация: 10.03.2002
Адрес: Israel
Сообщения: 245

alexey_ma Нимб уже пробиваетсяalexey_ma Нимб уже пробивается
Цитата:
Crazy_kettle:
Если запретить, то имхо в вектор ничего нельзя будет добавить . Кстати, Имхо вызов конструктора не вредит. Другое дело деструктор, но его я убрал . Память освобождается при очистке вектора.
Ну вы, блин даете. Это совсем плохо. Поробуйте одну и ту-же структуру дважды в вектор добавить. A? Как тогда будет память освобождаться?

Цитата:
Crazy_kettle:
Да при окончании программы вызывается деструктор для строки. Но т.к. s.str==NULL, то ф-ция free(s.str) НИЧЕГО не делает, а, значит, можно считать, что для структуры s деструктор вовсе отсутствует .
Не предусмотрел я то, что при реализации vector:ush_back может создаваться временный объект (что вы категорически отрицаете) и для него вызываться деструктор, который всё портит. Я не виню за это программистов Microsoft, это их дело как писать свои процедуры.
Цитата:
Да елы-палы. Нет там никакого временного объекта. Я же привел прототип push_back. push_back В ПАРАМЕТРЕ ПОЛУЧАЕТ КОСТАНТНУЮ ССЫЛКУ(РЕФЕРЕНС)
Код:
void push_back(
   const Type& _Val
);
Уважаемый, вы в курсе что такое ссылка он же референс?
Eще раз : Cоздается два объекта, один обьявленная вами локальная структура и ее копия в векторе. Оба этих объекта из-за отсутствия конструктора копирования имеют указатель char* str содержащий один и тот же адрес (это легко проверить в дебагире). Локальная структура уничтожается когда она выходит из скопа. Для неё вызывается деструктор в котором освобождается указатель str. Копия этой структуры уничтожается тогда когда вектор выходит из скопа. Вектор при удалении вызывает деструкторы для хранящихся в нём объектов. Следовательно деструктор копии пытается тоже освободить указатель str. Поскольку адрес хранящийся в этом указателе уже освобожден после вызова деструктора локальной структуры то происходит нарушение защиты памяти, в просторечии креш.
Если вы мне не верите то спросите любого програмиста хотя бы немного разбирающегося в С++ , он вам скажет то-же самое. А еще лучше, до того как начинаете писать код почитайте соответствующую литературу и ознакомтесь, наконец, с документацией на STL.
__________________
Best Regards

Последний раз редактировалось alexey_ma; 30.01.2006 в 23:07.
alexey_ma вне форума  
Старый 31.01.2006, 07:04     # 10
PSyton
Junior Member
 
Аватар для PSyton
 
Регистрация: 19.04.2002
Адрес: Дом
Пол: Male
Сообщения: 187

PSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форуме
Цитата:
Сообщение от Crazy_kettle
Интересует меня другое. Я ведь всегда думал, что STL разрабатывалась/писалась так, чтобы обеспечивать максимальное быстродействие. Только вот зачем нужно создавать временный объект? (конечно, программистам MS виднее, но разработчики библиотеки, поставляемой с g++ 3.4.4, обошлись же без этого). И это, имхо, создание временного объекта может отнимать уйму времени (если этот объект очень большой). Не зря же объекты передаются по ссылке ?!
Да ну? А насколько я помню, STL разрабатывался как средство, позволяющее быстро разрабатывать программные продукты, не тратя времени на написание своих контейнеров, списков и т.п. Там же, умный дядька Бьерн Страуструп писал, что, увы это имеет свои минусы, так как в некоторых случаях снижает быстродействие за счет универсализации.
Да и что значит "я потеряю в скорости"? Все относительно... Если у тебя 100 объектов, то ты можешь начихать на это, поскольку при современных скоростях это тьфу. К тому же при написании больших проектов, далеко не все упирается в скорость, но также еще и в возможность поддежки и расширения. Таким образом, написак конструктор копирования и оператор присваивания для класса 1 раз ты можешь забыть об этолм и без оглядки на всякие там особенности писать новый код с использованием объектов этого класса. На то он и C++ и ООП в частности - никто снаружи не должен заботится о выделеии/перевыделении/очистке памяти под твою внутреннюю строку.
А почему бы не использовать std::string вместо этой убогой структуры?
__________________
Дураки не динозавры - они не вымрут...
PSyton вне форума  
Старый 31.01.2006, 09:50     # 11
Drakosha
Full Member
 
Аватар для Drakosha
 
Регистрация: 16.10.2002
Адрес: ArchLinux, Internet
Сообщения: 557

Drakosha Реально крут(а)Drakosha Реально крут(а)Drakosha Реально крут(а)Drakosha Реально крут(а)
Цитата:
alexey_ma:
Уважаемый, вы в курсе что такое ссылка он же референс?
Eще раз : Cоздается два объекта, один обьявленная вами локальная структура и ее копия в векторе. Оба этих объекта из-за отсутствия конструктора копирования имеют указатель char* str содержащий один и тот же адрес (это легко проверить в дебагире). Локальная структура уничтожается когда она выходит из скопа. Для неё вызывается деструктор в котором освобождается указатель str. Копия этой структуры уничтожается тогда когда вектор выходит из скопа. Вектор при удалении вызывает деструкторы для хранящихся в нём объектов. Следовательно деструктор копии пытается тоже освободить указатель str. Поскольку адрес хранящийся в этом указателе уже освобожден после вызова деструктора локальной структуры то происходит нарушение защиты памяти, в просторечии креш.
1. Насчет того что наго писать copy constructor - это конечно правильно. 100% согласен
2. В данном случае объект не выходит из скопа до печати на экран. Как вы обясните поведение этой программы а не теоретическое поведение STL (которое вы объясняете совершенно правильно). Я вижу только одно объяснение - где-то временный объект таки создаётся. Кроме как в коде STL я для этого мест не вижу.
Drakosha вне форума  
Старый 31.01.2006, 11:47     # 12
alexey_ma
Member
 
Регистрация: 10.03.2002
Адрес: Israel
Сообщения: 245

alexey_ma Нимб уже пробиваетсяalexey_ma Нимб уже пробивается
Цитата:
Drakosha:
2. В данном случае объект не выходит из скопа до печати на экран. Как вы обясните поведение этой программы а не теоретическое поведение STL (которое вы объясняете совершенно правильно). Я вижу только одно объяснение - где-то временный объект таки создаётся. Кроме как в коде STL я для этого мест не вижу.
Ok. Понял что вас смущает. То что есть вызов деструктора до того как все объекты выходят из скопа. Для это нужно посмотреть реализацию функции вектора _Insert_n
Код:
	void _Insert_n(iterator _Where,
		size_type _Count, const _Ty& _Val)
		{	// insert _Count * _Val at _Where
		_Ty _Tmp = _Val;	// in case _Val is in sequence
		size_type _Capacity = capacity();

		if (_Count == 0)
			;
		else if (max_size() - size() < _Count)
			_Xlen();	// result too long
		else if (_Capacity < size() + _Count)
			{	// not enough room, reallocate
			_Capacity = max_size() - _Capacity / 2 < _Capacity
				? 0 : _Capacity + _Capacity / 2;	// try to grow by 50%
			if (_Capacity < size() + _Count)
				_Capacity = size() + _Count;
			pointer _Newvec = this->_Alval.allocate(_Capacity);
			pointer _Ptr = _Newvec;

			_TRY_BEGIN
			_Ptr = _Ucopy(_Myfirst, _ITER_BASE(_Where),
				_Newvec);	// copy prefix
			_Ptr = _Ufill(_Ptr, _Count, _Tmp);	// add new stuff
			_Ucopy(_ITER_BASE(_Where), _Mylast, _Ptr);	// copy suffix
			_CATCH_ALL
			_Destroy(_Newvec, _Ptr);
			this->_Alval.deallocate(_Newvec, _Capacity);
			_RERAISE;
			_CATCH_END

			_Count += size();
			if (_Myfirst != 0)
				{	// destroy and deallocate old array
				_Destroy(_Myfirst, _Mylast);
				this->_Alval.deallocate(_Myfirst, _Myend - _Myfirst);
				}
			_Myend = _Newvec + _Capacity;
			_Mylast = _Newvec + _Count;
			_Myfirst = _Newvec;
			}
		else if ((size_type)(_Mylast - _ITER_BASE(_Where)) < _Count)
			{	// new stuff spills off end
			_Ucopy(_ITER_BASE(_Where), _Mylast,
				_ITER_BASE(_Where) + _Count);	// copy suffix

			_TRY_BEGIN
			_Ufill(_Mylast, _Count - (_Mylast - _ITER_BASE(_Where)),
				_Tmp);	// insert new stuff off end
			_CATCH_ALL
			_Destroy(_ITER_BASE(_Where) + _Count, _Mylast + _Count);
			_RERAISE;
			_CATCH_END

			_Mylast += _Count;
			fill(_ITER_BASE(_Where), _Mylast - _Count,
				_Tmp);	// insert up to old end
			}
		else
			{	// new stuff can all be assigned
			pointer _Oldend = _Mylast;
			_Mylast = _Ucopy(_Oldend - _Count, _Oldend,
				_Mylast);	// copy suffix
			copy_backward(_ITER_BASE(_Where), _Oldend - _Count,
				_Oldend);	// copy hole
			fill(_ITER_BASE(_Where), _ITER_BASE(_Where) + _Count,
				_Tmp);	// insert into hole
			}
		}
Там где жирным виделено происходит копирование объекта в локальный объект _Tmp. Его деструктор вам и мешает. Поэтому в вашей программе деструктор будет вызыватся три раза а не два. Причем первый раз до выхода объектов из скопа сразу после строки vec.push_back(s);
__________________
Best Regards

Последний раз редактировалось alexey_ma; 31.01.2006 в 11:54.
alexey_ma вне форума  
Старый 31.01.2006, 17:03     # 13
Drakosha
Full Member
 
Аватар для Drakosha
 
Регистрация: 16.10.2002
Адрес: ArchLinux, Internet
Сообщения: 557

Drakosha Реально крут(а)Drakosha Реально крут(а)Drakosha Реально крут(а)Drakosha Реально крут(а)
ну вот, все согласны
радует что в g++ STL сделанно лучше

Последний раз редактировалось Drakosha; 01.02.2006 в 09:52.
Drakosha вне форума  
Старый 31.01.2006, 23:03     # 14
Crazy_kettle
Junior Member
 
Регистрация: 13.05.2004
Сообщения: 128

Crazy_kettle Известность не заставит себя ждатьCrazy_kettle Известность не заставит себя ждать
alexey_ma вы наверное очень умный, но, имхо, это не значит, что это даёт Вам право [внимательно\вовсе] НЕ читать посты других участников.
Цитата:
Сообщение от alexey_ma
Локальная структура уничтожается когда она выходит из скопа. Для неё вызывается деструктор в котором освобождается указатель str.
Во первых, вы уже сами поняли, что лок. переменная до возникновения неправильного вывода из скопа не выходила, но об этом написано начиная с первого поста:
Цитата:
Сообщение от crazy_kettle
ведь переменная s и вектор vec ещё используются (не говоря уже об области видимости)
Писалось также, что я специально принял меры, чтобы избежать "пагубного" влияния вызова деструктора для переменной s. В первом посте (в виде комментария) и в посте http://www.imho.ws/showpost.php?p=1119412&postcount=8:
Цитата:
Сообщение от crazy_kettle
Да при окончании программы вызывается деструктор для строки. Но т.к. s.str==NULL, то ф-ция free(s.str) НИЧЕГО не делает, а, значит, можно считать, что для структуры s деструктор вовсе отсутствует
Я понимаю, что это решения может быть галимым, но тогда нужно, имхо, это решение и обсуждать, а не говорить то, что мне и так понятно (хотя Вы мне в этом не верите ).
Это так было сказано к слову и не значит, что я горю расжигать перебранку.
Цитата:
Сообщение от PSyton
Цитата:
Сообщение от Crazy_kettle
STL разрабатывалась/писалась так, чтобы обеспечивать максимальное быстродействие.
Да ну?
От стандартной библиотеки не просто требуется выполнять свои задачи, она также должна выполнять их достаточно эффективно, чтобы у пользователя не позникло соблазна использовать совственные механизмы. (Страуструп. Язык С++. 2002 год. стр. 487). И ещё где-то он писал, что перед тем, чтобы думать, что ваше средство эффективнее стандартного, проведите широкомаштабное исследование.
Цитата:
Сообщение от PSyton
Если у тебя 100 объектов, то ты можешь начихать на это, поскольку при современных скоростях это тьфу. К тому же при написании больших проектов, далеко не все упирается в скорость, но также еще и в возможность поддежки и расширения.
С одной стороны Вы правы, но с другой, хочется, уже сейчас заботится об эффективности. Более того, что я писал не большой проект, а прогу для себя (хоть и не маленькую). И мне хотелось её побыстрее склепать.
Цитата:
Сообщение от PSyton
А почему бы не использовать std::string вместо этой убогой структуры?
В данном примере Вы несомненно правы. Но здесь приведён не кусок того исходного кода (было выловлено место ошибки и написан специально под неё пример). Конечно, в программе можно было заменить все char* на string, но это решено было не делать по следующим причинам:
1) (уже писалось почему) Решено было использовать стандартную библиотеку С и WinAPi для работы с файлами и каждый раз конвертить string в char* надоело бы, да и неизвестно мне насколько это эффективно
2) Нельзя использовать string::c_str() для изменения, что доставляло бы хлопот при работе с нек. функциями, например с fwrite.
3) В этом случае возможны ненужные выделения памяти
Crazy_kettle вне форума  
Старый 01.02.2006, 10:26     # 15
alexey_ma
Member
 
Регистрация: 10.03.2002
Адрес: Israel
Сообщения: 245

alexey_ma Нимб уже пробиваетсяalexey_ma Нимб уже пробивается
Цитата:
Crazy_kettle:
Я понимаю, что это решения может быть галимым, но тогда нужно, имхо, это решение и обсуждать, а не говорить то, что мне и так понятно (хотя Вы мне в этом не верите ).
Давайте обсудим решение.
Я же привел вам нормальное ( относительно конечно , я бы все равно так бы не писал) решение в третьем посте, с нормальным конструктором и с нормальным использованием вектора. Чем оно не понравилось ? Ваше решение изначально кривое, вы не правильно работаете с вектором и последствия этой неправильной работы пытаетесь заткнуть с помощью всяких ухищрений при этом обвиняя STL в плохой реализации. Еще раз настоятельно советую почитать документацию по STL. Возможно даже сможете вместо fwrite использовать стримы STL.
Цитата:
Crazy_kettle:
Решено было использовать стандартную библиотеку С и WinAPi для работы с файлами и каждый раз конвертить string в char* надоело бы, да и неизвестно мне насколько это эффективно
Вы еще даже не знаете насколько это эффективно или нет а уже пытаетесь бороться с неэффективностью посредством кривого кода. Почему - бы сначала не проверить? Возможно, не придеться изобретать велосипед.
Посчему бы не использовать STL для работы с файлам вместо WinAPi?

Цитата:
Drakosha:
радует что в g++ STL сделанно лучше
Если не влом, приаттачте vector.h из gcc.Любопытно, насколько они отличаются.
__________________
Best Regards
alexey_ma вне форума  
Старый 01.02.2006, 11:32     # 16
PSyton
Junior Member
 
Аватар для PSyton
 
Регистрация: 19.04.2002
Адрес: Дом
Пол: Male
Сообщения: 187

PSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форумеPSyton Популярный человек на этом форуме
Цитата:
Сообщение от alexey_ma
Если не влом, приаттачте vector.h из gcc.Любопытно, насколько они отличаются.
Пожалуйста, только по моему одного вектора будет мало...
Ну да ладно.
Вложения
Тип файла: zip stl_vector.zip (7.2 Кбайт, 1 просмотров - Кто скачивал? )
__________________
Дураки не динозавры - они не вымрут...
PSyton вне форума  
Старый 01.02.2006, 12:47     # 17
alexey_ma
Member
 
Регистрация: 10.03.2002
Адрес: Israel
Сообщения: 245

alexey_ma Нимб уже пробиваетсяalexey_ma Нимб уже пробивается
Да. Ничего общего.
Вложения
Тип файла: zip vector.zip (6.9 Кбайт, 0 просмотров )
__________________
Best Regards
alexey_ma вне форума  
Старый 02.02.2006, 01:20     # 18
Crazy_kettle
Junior Member
 
Регистрация: 13.05.2004
Сообщения: 128

Crazy_kettle Известность не заставит себя ждатьCrazy_kettle Известность не заставит себя ждать
to alexey_ma
Такое ощущение, что мы говорим на разных языках.
Цитата:
Сообщение от alexey_ma
Давайте обсудим решение.
Я же привел вам нормальное ( относительно конечно , я бы все равно так бы не писал) решение в третьем посте, с нормальным конструктором и с нормальным использованием вектора. Чем оно не понравилось ?
Здесь имелось ввиду (что, кажется мне очевидным, читая пост http://www.imho.ws/showpost.php?p=1120117&postcount=14) моё бывшее решение проблемы вызова деструктора для структуры и для элемента вектора :
Цитата:
Сообщение от Crazy_kettle
s.str=0;//Чтобы деструктор не пытался освободить память повторно.
. Т.е. обсудить эту строчку, порождённые ей проблемы (ту, что она не решает проблему вызова деструктора во временном объекте я знаю, если будут другие мысли то пишите), а не говорить мне постоянно про существование деструкторов и всякие там кросс-референсы. Особенно, учитывая, что я ПИСАЛ, что как-раз эту проблему я учитывал и пытался решать.
Что насчёт вашего решения, то она мне не понравилось из-за ТРЁХ НЕ нужных выделений и освобождений памяти. К тому же ваше решение "педалится", если строка содержит символ '\0' (конечно, со string это не проблема и Ваш вариант можно немного модифицировать, но это так к слову)
Цитата:
Сообщение от alexey_ma
вы не правильно работаете с вектором и последствия этой неправильной работы пытаетесь заткнуть с помощью всяких ухищрений при этом обвиняя STL в плохой реализации
Прочитайте, пожалуйста, пост http://www.imho.ws/showpost.php?p=1119412&postcount=8 после цитаты поста PSyton. Там, вроде, понятно написано, что я не виню программистов MS за мой "кривой" код с багом. А только говорю, что это развеяло моё представление, что STL (STL от MS ) разрабатывается так, чтобы обеспечить максимально-возможное быстродействие.
Цитата:
Сообщение от alexey_ma
Посчему бы не использовать STL для работы с файлам вместо WinAPi?
Я просто не знаю так средствами STL вывести все файлы папки по маске, прочитать/изменить права/аттрибуты. Если это можно, по пишите.
[hr]

И вообще alexey_ma я считаю, что не нужно развивать эту тему .
Я знаю, что мой код "кривой". Но также знаю, что этот код писался для меня и врядли будет сопровождаться и маштабироваться .
Более того, я понял, что малой кровью от "кривизны" (в моём понимании) не избавиться. Поэтому, возможно, в будущем всё перепишется, когда больше прокачаюсь. А сейчас я не вижу лезть в код, кот., вроде, прекрасно пока работает.
Crazy_kettle вне форума  


Ваши права в разделе
Вы НЕ можете создавать новые темы
Вы не можете отвечать в темах.
Вы НЕ можете прикреплять вложения
Вы НЕ можете редактировать свои сообщения

BB код Вкл.
Смайлы Вкл.
[IMG] код Выкл.
HTML код Выкл.

Быстрый переход


Часовой пояс GMT +4, время: 15:04.




Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.