Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
Sasha_builder Гость
|
Добавлено: Пт Янв 18 2002 21:09 Заголовок сообщения: Можно ли |
|
|
Привествую всех.
Кто может прояснить, можно ли присваивать значения указателям. Я понимаю, что запретить мне этого никто не может, но меня интересует корректны ли такие действия с точки зрения ОС (ДОС и Виндоуз). Привожу пример программы. Она работает, но я не уверен, можно ли такими приемами пользоваться в более критических (по использованию памяти) программах.
#include #include
//глобальный указатель int *PtrGlob;
void ArraySetting(int n) { int *ptrLoc;
//запрос памяти, используя локальный указатель ptrLoc=new int[n];
//присваивание значения локального ук. глобальному PtrGlob=ptrLoc;
}
void main() { int i,n=1000;
//создание массива во внешней функции ArraySetting(n);
//использование глобального массива for(i=0;i |
|
Вернуться к началу |
|
|
zzz
Зарегистрирован: 02.02.2002 Сообщения: 66 Откуда: Rostov-on-Don
|
Добавлено: Сб Янв 19 2002 08:47 Заголовок сообщения: можно, а пример не ботал (-) |
|
|
- |
|
Вернуться к началу |
|
|
Алексанлр Гость
|
Добавлено: Сб Янв 19 2002 15:52 Заголовок сообщения: Re: Можно ли |
|
|
Не совсем понятно где пример не работает.
Лично мой совет избегай использования глобальных переменных по возможности.
Что касается примера я лично не увилел, а где же ты уничтожаеш свой массив ? delete []указатель на массив; может в этом проблема ? |
|
Вернуться к началу |
|
|
Александр
Зарегистрирован: 07.10.2003 Сообщения: 276
|
Добавлено: Сб Янв 19 2002 15:57 Заголовок сообщения: Re: Можно ли |
|
|
Вдогонку , а как ты обращаешся к элементам массива? |
|
Вернуться к началу |
|
|
Sasha_builder Гость
|
Добавлено: Сб Янв 19 2002 20:04 Заголовок сообщения: Re: Можно ли |
|
|
Спасибо, Александр.
Что касается примера, я тоже мало что там увидел, я не знаю, что нужно делать, чтобы не съедался текст, когда постишь примеры. Послал имейл на info@citforum.ru - ни ответа ни привета.
К делу. Пример работает. Ты несомненно прав с глобальными переменными (избегать по возможности), я следую этому правилу. Так вот, уничтожение и есть штука в которой я не уверен (в смысле как на это смотрит ОС). Я прошу памяти во внешней функции для ее локального указателя, присваиваю его значение глобальному (это все можно увидеть в остатках примера), потом использую этот глобальный указатель в функции main() как массив. Вот теперь, могу ли я применить оператор delete к этому глобальному указателю? Вроде я встречал в руководствах, что применение этого оператора к указателю, к которому не применялся new, может приводить к зависанию (по крайней мере для ДОС). У меня как раз такая ситуация: new к локальному указателя, delete к глобальному. Есть идеи? Извини за многословность, но боюсь опять на примере показать не получилось бы.
Александр |
|
Вернуться к началу |
|
|
Sasha_builder Гость
|
Добавлено: Сб Янв 19 2002 20:19 Заголовок сообщения: Re: Можно ли |
|
|
так: PtrGlob[5]=37; a=PtrGlob[5]; |
|
Вернуться к началу |
|
|
zzz
Зарегистрирован: 02.02.2002 Сообщения: 66 Откуда: Rostov-on-Don
|
Добавлено: Сб Янв 19 2002 20:24 Заголовок сообщения: так new и delete должно работать, им пофигу, если пишешь правильно. (-) |
|
|
- |
|
Вернуться к началу |
|
|
Александр
Зарегистрирован: 07.10.2003 Сообщения: 276
|
Добавлено: Вс Янв 20 2002 01:32 Заголовок сообщения: так пример работает ? |
|
|
Что лично я понял по поводу этих операторов: 1.Присваивать указателю можешь адрес на любой объект но заботиться об уничтожении должен сам. 2.при создании объекта с помощью new указывается тип переменной (класс), это позволяет удалить объект без приведения типов (именно по этой причине более современными считаются функции new и delete в отличии от malloc ), в твоем случае колизия заключается видимо в следующем: есть глобальный указатель int *global, ты создал массив и присвоил адрес первого элемента этому указателю int *local=new int[10] global=local, а теперь представь, ты удаляешь массив или delete []local или delete []global В первом случае функция delete знает, что удалить надо именно десять єлементов типа int (компилятор это понимает поскольку имя одно и тоже).А откуда во втором случае можно узнать, что удалить надо именно десять, а не двадцать элементов ??? Видимо необходимо почитать как это делалось для функций malloc и free в случае массива. 3. При объявлении указателя обязательно присваивай ему либо NULL, либо (разные авторы советуют по разному,в этом есть небольшая разница). тогда if(global!=NULL) delete global; при удалении объекта его указатель получает значение NULL |
|
Вернуться к началу |
|
|
Sasha_builder Гость
|
Добавлено: Вс Янв 20 2002 05:02 Заголовок сообщения: Работает, но... |
|
|
Александр,
компилятор тут не при чем, так как запрос памяти происходит в период исполнения. Должно что-то происходить на уровне ОС, которая эту память выделяет. Вот тут-то мои знания заканчиваются.
Пример вообще-то работает. Но это лишь очень упрощенная (принципиальная) схема более сложной программы, где постоянные запросы памяти и обратная ее отдача - главные составляющие. Что-то там у меня творится с памятью, но никак не могу понять что, поэтому для начала решил прояснить этот вопрос, так сказать на теоретическом уровне.
Спасибо тебе за ответы.
Александр. |
|
Вернуться к началу |
|
|
Sasha_builder Гость
|
Добавлено: Вс Янв 20 2002 05:04 Заголовок сообщения: Re: так new и delete должно работать, им пофигу, если пишешь правильно. (-) |
|
|
zzz,
правильно ли я пишу - это и было то что я не знал...
Спасибо за ответ!
Александр |
|
Вернуться к началу |
|
|
zzz
Зарегистрирован: 02.02.2002 Сообщения: 66 Откуда: Rostov-on-Don
|
Добавлено: Вс Янв 20 2002 11:43 Заголовок сообщения: не согласен |
|
|
организует освобождение памяти не компилятор, запоминая, то раз для x выделено 10 байт, то 10 байт и надо прибивать. Это все реализуется самой системой. И компилятор никакие имена, конечно, не запоминает, потому как имен-то и нету. Создай массив из указателей на массив из указателей и так далее, любой вложенности. И если аккуратно писать, все будет правильно освобождаться. Многие функции WINAPI (в частности, Net*) получают на вход пустой указатель, сами создают буфер, не возвращая его размер, и этот указатель потом отдается в NetApiBufferFree. Одними глобальными или локальными переменными тут не обойтись.
А почему new и delete более современные? Они только реализацию скрывают, и для более или менее сложных классов требуют подчас ненужной перегрузки, в отличие от malloc.
при удалении объекта его указатель получает значение NULL а это смотря как удалять, в абсолюте заявление более чем голословное. |
|
Вернуться к началу |
|
|
Александр
Зарегистрирован: 07.10.2003 Сообщения: 276
|
Добавлено: Вс Янв 20 2002 15:21 Заголовок сообщения: Re: не согласен |
|
|
Компилятор тут наверное действительно не причем, но откуда программа или ОС знает, что при применении delete к глобальному указателю что это указатель не на один int, а на массив. По моему в примере речь шла имеенно об этом.
Не уверен в своей правоте но всетаки выслушал бы еще аргументы. |
|
Вернуться к началу |
|
|
Александр
Зарегистрирован: 07.10.2003 Сообщения: 276
|
Добавлено: Вс Янв 20 2002 15:37 Заголовок сообщения: Re: не согласен |
|
|
Кстати а какие системы заботятся об уничтожении данных размещаемых программой в куче ? Я думал это дело самих программ. |
|
Вернуться к началу |
|
|
zzz
Зарегистрирован: 02.02.2002 Сообщения: 66 Откуда: Rostov-on-Don
|
Добавлено: Вс Янв 20 2002 16:10 Заголовок сообщения: так вот, |
|
|
когда дело касается удаления, пишется же не delete, а delete[]. Короче, потому я new и delete и не люблю, что они реализацию скрывают. А delete применяется для каждого элемента. Короче, для каждого объекта определяется действие delete. А уж это действие может и другие delete вызывать.
Освобождение ресурсов - это и дело самих программ, и не только. Даже в случае самих программ это дело программиста, как в случае С, или реализована сборка мусора, как в SmallTalk. Например, в NT/2000 можно не закрывать файлы, система их сама закроет, по крайней мере, должна. И для процесса в ядре создаются структуры данных, которые хранят все его открытые хэндлы. При выделении и освобождении памяти не составляет труда определить контекст вызова, и в конце даже в случае смерти программы освободить память и ресурсы. На 9x такие фокусы, насколько я понимаю, не пройдут. |
|
Вернуться к началу |
|
|
zzz
Зарегистрирован: 02.02.2002 Сообщения: 66 Откуда: Rostov-on-Don
|
Добавлено: Вс Янв 20 2002 16:15 Заголовок сообщения: при выделении памяти |
|
|
выделяется системой больше, чем просишь. Прозрачная реализация такого механизма обеспечивается диспетчером памяти на уровне ядра. А все указатели - они только идентифицируют тот объект в ядре, который определяет адрес выделяемого объема памяти, его контекст защиты, его тип доступа и тому подобное. А все вызовы WINAPI транслируются в соответствующие функции ядра, в том числе при выделении и освобождении памяти. |
|
Вернуться к началу |
|
|
appower Гость
|
Добавлено: Ср Янв 23 2002 22:28 Заголовок сообщения: Re: for lamers |
|
|
В пределах одного процесса, глобальному ука- зателю можешь присвоить даже указатель на свои тупые мозги. |
|
Вернуться к началу |
|
|
Sasha_builder Гость
|
Добавлено: Чт Янв 24 2002 00:08 Заголовок сообщения: Возможно ты прав, а что-нибудь конструктивнее? |
|
|
Насчет тупых мозгов - извини.
И все-таки, как поступить? |
|
Вернуться к началу |
|
|
appower Гость
|
Добавлено: Пт Янв 25 2002 00:00 Заголовок сообщения: Re: Возможно ты прав, а что-нибудь конструктивнее? |
|
|
char * global_pointer = 0; //--------------------------------- struct s { char a; int b; }; //--------------------------------- void f1(int *val) { val = new int[3]; } //--------------------------------- void f2(char *val) { val = new char[3]; } //--------------------------------- void f3(struct s *val) { val = new s[3]; } //--------------------------------- int main() { f1(reinterpret_cast(global_pointer)); delete[]global_pointer; f2(global_pointer); delete[]global_pointer; f3(reinterpret_cast (global_pointer)); delete[]global_pointer; return 0; } //------------------------------------- создание массива во внешней функции
Внешней чему???????????????????????? Процессу??? Любые указатели корректны, если ты не переда- ешь их после вызовов CreateProcess(fork,clone и т.п.) в ф-и дочерних или внешних процессов. |
|
Вернуться к началу |
|
|
Alexy
Зарегистрирован: 22.10.2003 Сообщения: 48
|
Добавлено: Вс Янв 27 2002 10:15 Заголовок сообщения: Oops |
|
|
К сожалению этот пример упадёт уже на второй строчке main() - "delete[]global_pointer;" с диагнозом access violation или segmentation fault в UNIX и вот почему:
любая программа имеет 4 сегмента 1. code segment - здесь расположены команды для процессора 2. data segment - здесь расположены глобальные данные процесса/ов (*.exe + dll-и) 3. stack segment - сюда пишут много всего, а среди прочего порядок вызова функций и локальные переменные, в том числе параметры функций 4. heap - здесь размещается динамически выделяемая память (new, malloc)
Глобальные переменные обязательно инициализируются в NULL, чтобы следующий код мог правильно сработать:
SomeSingleton* SomeSingleton::instance = SomeSingleton::getInstance(); int* SomeSingleton::getInstance() { if(!instance) instance = new SomeSingleton; return instance; } Теперь, что написано в 1 строчки main() 1. положи в stack СОДЕРЖИМОЕ global_poiner, это NULL. Не адрес global_poiner, а то что записано по этому адресу 2. всё необходимое для вызова функции 3. call @f1@@int ( ) 4. запиши в стек по адресу куда был записан NULL) результат new int[3] 5. очисти stack и сделай return (порядок очистки зависит от calling convention)
В результате у нас есть аллоцированный блок в heap-e, адреса которого мы не знаем и global_pointer (скажем его адрес будет 2000h) Так вот, байты 2000h-2003h равны нулю или попросту global_pointer равен нулю
Поэтому 2 строчка будет означать delete NULL; или delete[] NULL; или free(NULL); |
|
Вернуться к началу |
|
|
appower Гость
|
Добавлено: Вс Янв 27 2002 16:14 Заголовок сообщения: Re: Oops |
|
|
Быстро писал. Да ради Бога напиши f1(void **) или f1(void*&)и присваивай что угодно.Да конечно со стековой переменной слегка лоханулся,но это не принципиально для сути вопроса,а к мелочам не придирайся, развел демагогию с правилами правописания! |
|
Вернуться к началу |
|
|
Alexy
Зарегистрирован: 22.10.2003 Сообщения: 48
|
Добавлено: Вс Янв 27 2002 18:41 Заголовок сообщения: Re: Pardon |
|
|
А аткендава ж я знаю, может ты всерьёз насчёт f(void*) ??? |
|
Вернуться к началу |
|
|
|