Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.65/37: Рейтинг темы: голосов - 37, средняя оценка - 4.65
0 / 0 / 0
Регистрация: 08.02.2013
Сообщений: 26
1

delete[] статической памяти

18.05.2013, 03:56. Показов 7285. Ответов 45
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
1. Должна ли возникать ошибка (или падение программы) при применении delete[] к статической памяти? У меня (Microsoft Visual Studio 2005) никаких ошибок не возникает. Но, просто, сталкивался с тем, что на некой 64-х разрядной машине (Windows), при запуске моей 32-х разрядной программы (то есть в эмуляторе) она вылетала в месте где используется delete[] к статической переменной. А также встречал в интернете вопросы о ошибке при delete[] статической памяти, но там не указывался компилятор.

2. Если вылетание при delete[] статической памяти возможно, то как узнать какой указатель: на динамическую память или статическую. Теоретически мне это не предсnавляется сложным. Если этого нету в C/C++, то может такая возможность есть в WinApi?
Вот, например, есть в функция в которую передается char*. И эта память освобождается в функции. Но в функцию ведь может быть передана и константа и указатель на статическую память.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.05.2013, 03:56
Ответы с готовыми решениями:

Переменные в статической и динамической памяти!
Народ, подскажите как этот рисунок перевести в программу! тоесть как с помощью программы разместить...

Выделение статической памяти, не используя статические объекты
Здравствуйте! Как известно, когда мы объявляем статическую переменную, то компилятор выделяет ей...

Возможно ли обращение к статической памяти функции извне?
Здравствуйте! Возможно ли сделать так? Obj* ptr; void F() { static Obj _obj = { }; ...

delete[] *pointer vs. delete pointer и утечка памяти
Здравствуйте! Есть класс "умного" указателя counted_ptr, который удаляет хранящийся в нём T*...

45
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
20.05.2013, 20:17 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от faridenco Посмотреть сообщение
Потому что так короче и удобней, умник.
Держите свои эмоции при себе, не переходите на личности.
Не ответили на вопрос потому что ответ на него есть в любой более или менее приличной книге по C++ для начинающих. В частности говорится о том, что память под статические объекты выделяется при запуске программы, и освобождается при ее завершении, никакие delete ее не освободят.
http://en.wikipedia.org/wiki/Data_segment
A data segment is a portion of virtual address space of a program, which contains the global variables and static variables that are initialized by the programmer. The size of this segment is determined by the values placed there by the programmer before the program was compiled or assembled, and does not change at run-time.
Добавлено через 2 минуты
Цитата Сообщение от faridenco Посмотреть сообщение
Поначалу писали что это ошибка, а оказалось что стандарт это не определяет как ошибку.
Смотря что подразумевать под ошибкой. Данный код ошибочен, так как это чистый UB, он не соответствует стандарту. Не нужно рассчитывать в этом случае на компилятор, в следующей версии поведение может кардинально измениться.
1
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
20.05.2013, 20:18 22
Цитата Сообщение от faridenco Посмотреть сообщение
Поначалу писали что это ошибка, а оказалось что стандарт это не определяет как ошибку.
Стандартом это квалифицируется, как неопределенное поведение (undefined behavior, UB).
Разве этого не достаточно ?

Цитата Сообщение от faridenco Посмотреть сообщение
Впрочем я итак знаю, что программа, скомпилированная компилятором Microsoft, ничего не делает когда встречает delete[] по отношению к статической памяти.
Это не так.
Попробуйте, например, вызвать "operator delete []" на адресе
какой-нибудь статической или глобальной переменной.
Скорее всего, получите разрушение кучи (heap corruption).
1
0 / 0 / 0
Регистрация: 08.02.2013
Сообщений: 26
20.05.2013, 20:39  [ТС] 23
Цитата Сообщение от Toshkarik Посмотреть сообщение
Держите свои эмоции при себе, не переходите на личности.
Не ответили на вопрос потому что ответ на него есть в любой более или менее приличной книге по C++ для начинающих. В частности говорится о том, что память под статические объекты выделяется при запуске программы, и освобождается при ее завершении, никакие delete ее не освободят.
http://en.wikipedia.org/wiki/Data_segment


Добавлено через 2 минуты

Смотря что подразумевать под ошибкой. Данный код ошибочен, так как это чистый UB, он не соответствует стандарту. Не нужно рассчитывать в этом случае на компилятор, в следующей версии поведение может кардинально измениться.
Я прекрасно осведомлен как устроена память, как она выделяется и освобождается. Я знаю, что delete[] не освобождает статическую и автоматическую память. Вопрос мой совсем был не об этом. Перечитай мои сообщения.

Добавлено через 9 минут
Цитата Сообщение от Убежденный Посмотреть сообщение
Попробуйте, например, вызвать "operator delete []" на адресе
какой-нибудь статической или глобальной переменной.
Скорее всего, получите разрушение кучи (heap corruption).
Я еще в первом посте написал, что в реализациях от Micrsoft я такого не замечал. Я указал свой компилятор. Что мне пробовать, когда я так везде пишу на своем компиляторе, еще ни одна программа не вылетала. Падала только при запуске на эмуляторе, в 64-х битной винде (32-х битная программа). Впроем и о этом я уже писал.

Добавлено через 7 минут
Стандартом это квалифицируется, как неопределенное поведение (undefined behavior, UB).
Это означает, что стандартом поведение не определено, а не то что поведение программы непредсказуемо ). Это означает, что разработчик компилятор сам решает как обработать эту ситуацию. То есть все зависит от реализации.
Вот пример я уже привел. В реализации от Microsoft ничего не делается. Куча повреждается если пишешь в динамическую память по адресу, не выделенному оператором new.
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
20.05.2013, 20:52 24
C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
 
int value = 123;
 
int main()
{
    delete [] &value;
    std::cout << value << std::endl;
    return 0;
}
Отладочная версия вылетает с сообщением "Debug Assertion Failed (_BLOCK_TYPE_IS_VALID).
Релизная версия вылетает с исключением 0xC0000374 (Heap Corruption).
Проверил на VC++ 2008/2010/2012.
2
0 / 0 / 0
Регистрация: 08.02.2013
Сообщений: 26
20.05.2013, 21:05  [ТС] 25
Цитата Сообщение от Убежденный Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
 
int value = 123;
 
int main()
{
    delete [] &value;
    std::cout << value << std::endl;
    return 0;
}
Отладочная версия вылетает с сообщением "Debug Assertion Failed (_BLOCK_TYPE_IS_VALID).
Релизная версия вылетает с исключением 0xC0000374 (Heap Corruption).
Проверил на VC++ 2008/2010/2012.
Мой компилятор (Microsoft Visual Studio 2005) в дебаге не выдал никаких ошибок. Благодарю, что вы пишите по теме. Именно это мне и было интересно узнать. То есть, на сколько Microsoft придерживается определенному правилу в своей реализации. Теперь я знаю, что в других компиляторах Microsoft будет ошибка.

Добавлено через 5 минут
И в релизе тоже разумеется у меня ошибок нет.
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
20.05.2013, 21:29 26
Давайте вернемся к тому, с чего начали.

Цитата Сообщение от faridenco Посмотреть сообщение
1. Должна ли возникать ошибка (или падение программы) при применении delete[] к статической памяти?
Согласно стандарту, не должна. Но указывается, что в этом случае поведение не определено.
То есть, в зависимости от комбинации "компилятор-платформа" и других факторов, может
возникнуть все, что угодно - от "замалчивания", которое наблюдается на VC++ 2005, до
выбрасывания исключений и порчи данных.

Добавлю, что delete-выражение корректно только тогда, когда ему передается не только
правильное значение указателя, но и его тип:

C++
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
#include <iostream>
 
 
 
class foo
{
public:
    foo()
    {
        std::cout << "create" << std::endl;
    }
 
    ~foo()
    {
        std::cout << "destroy" << std::endl;
    }
};
 
 
 
foo *create_foo()
{
    return (new foo());
}
 
void destroy_foo(void *pFoo)
{
    delete pFoo;
}
 
 
 
int main()
{
    foo *pFoo = create_foo();
    destroy_foo(pFoo);
    return 0;
}
Вывод данной программы (VC++ 2012):
> create
Как видим, деструктор foo не был вызван.
Кстати, не удивляйтесь, если на каком-то компиляторе эта программа завершится с ошибкой
или повиснет, так как это тоже undefined behavior.

И я могу объяснить, почему Стандартом здесь не предусмотрен выброс какого-нибудь исключения,
что было бы благом. Причина - оптимизация. Указатели хранят лишь адрес ячейки памяти, без
информации о типах и тому подобного. Подразумевается, что программист сам следит за
правильным удалением объектов и "не платит за то, что не использует".

Цитата Сообщение от faridenco Посмотреть сообщение
2. Если вылетание при delete[] статической памяти возможно, то как узнать какой указатель: на динамическую память или статическую.
Никак.
Этот вопрос решается на другом уровне - "политика владения".
Обычно на уровне всего исходного кода проекта поддерживается ряд ограничений по поводу
того, какие функции могут создавать и удалять объекты, а какие нет.
Например, функция, принимающая указатель, обычно не освобождает его, оставляя это на
совести вызывающего кода. Это один из простейших паттернов владения объектами.
Кроме этого, вместо "голых" указателей надежнее применять смарт-поинтеры и программные
интерфейсы, самостоятельно реализующие управление временем жизни объектов. Например,
подсчет ссылок. Это очень распостраненный подход на C++, где есть такие вещи, как RAII.
Количество ошибок, связанных с управлением памятью, при таком подходе сильно снижается.
1
0 / 0 / 0
Регистрация: 08.02.2013
Сообщений: 26
20.05.2013, 21:36  [ТС] 27
Да, я осведомлен о smart-pointer-х. Просто ищу способы как обходится без них.
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
20.05.2013, 21:36 28
Убежденный, зачем здесь delete для массива?
1
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
20.05.2013, 21:42 29
Цитата Сообщение от alsav22 Посмотреть сообщение
Убежденный, зачем здесь delete для массива?
"Здесь" - это где именно ?
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
20.05.2013, 21:47 30
Цитата Сообщение от Убежденный Посмотреть сообщение
"Здесь" - это где именно ?
C++
1
2
3
4
5
6
7
8
9
10
11
 
#include <iostream>
 
int value = 123;
 
int main()
{
    delete [] &value;
    std::cout << value << std::endl;
    return 0;
}
1
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
20.05.2013, 21:50 31
Взято из вопроса топикстартера:

Цитата Сообщение от faridenco Посмотреть сообщение
1. Должна ли возникать ошибка (или падение программы) при применении delete[] к статической памяти?
1
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
20.05.2013, 22:15 32
Цитата Сообщение от faridenco Посмотреть сообщение
Значит тогда "динамической памяти" тоже нету
Динамической нету. Есть динамически распределяемая, которая распределяется на что-то, сама память не расширяется, сколько она вмещает, столько и будет вмещать, больше в нее не засунешь.

Не по теме:

и вообще раздули из мухи слона

0
0 / 0 / 0
Регистрация: 08.02.2013
Сообщений: 26
20.05.2013, 23:35  [ТС] 33
Цитата Сообщение от daslex Посмотреть сообщение
Динамической нету. Есть динамически распределяемая, которая распределяется на что-то, сама память не расширяется, сколько она вмещает, столько и будет вмещать, больше в нее не засунешь.

Не по теме:

и вообще раздули из мухи слона

Это был риторический вопрос. Термин "динамическая память" употребляется к языкам програмирования. А на твою писанину для дедсада мне наплевать.
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
20.05.2013, 23:38 34
faridenco, тебе еще на первых двух страницах сказали ответ, дедуля.
0
0 / 0 / 0
Регистрация: 08.02.2013
Сообщений: 26
20.05.2013, 23:44  [ТС] 35
Цитата Сообщение от daslex Посмотреть сообщение
faridenco, тебе еще на первых двух страницах сказали ответ, дедуля.
Советую в таком случае внимательно все перечитать.
А вообще ответ не дан до сих пор. Я спрашивал про реализации (компиляторы). Более менее имею представление о компилторах Microsoft. А об этом мне ответили на третьей странице. Ни о каких больше реализациях мне не отвечали.
Но, то что это не ошибка, а поведение зависит от реализации - это точно.
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
20.05.2013, 23:53 36
faridenco, очки надень и посмотри

Добавлено через 8 минут
Цитата Сообщение от faridenco Посмотреть сообщение
1. Должна ли возникать ошибка (или падение программы) при применении delete[] к статической памяти? У меня (Microsoft Visual Studio 2005) никаких ошибок не возникает. Но, просто, сталкивался с тем, что на некой 64-х разрядной машине (Windows), при запуске моей 32-х разрядной программы (то есть в эмуляторе) она вылетала в месте где используется delete[] к статической переменной. А также встречал в интернете вопросы о ошибке при delete[] статической памяти, но там не указывался компилятор.
2. Если вылетание при delete[] статической памяти возможно, то как узнать какой указатель: на динамическую память или статическую. Теоретически мне это не предсnавляется сложным. Если этого нету в C/C++, то может такая возможность есть в WinApi?
Вот, например, есть в функция в которую передается char*. И эта память освобождается в функции. Но в функцию ведь может быть передана и константа и указатель на статическую память.
Где?
Цитата Сообщение от faridenco Посмотреть сообщение
Я спрашивал про реализации (компиляторы)
0
0 / 0 / 0
Регистрация: 08.02.2013
Сообщений: 26
20.05.2013, 23:54  [ТС] 37
Цитата Сообщение от daslex Посмотреть сообщение
faridenco, очки надень и посмотри
По первому посту ясно, что меня интересует поведение программы при delete[] статической памяти. И что на моем компиляторе нет ошибок. А значит нужна информация о реализациях. Ответ поведение зависит от реализации (undefined behavior) - не ответ.

На первой странице я уточнил (когда мне все еще твердили, что это ошибка).
Поэтому и спрашиваю, как на это смотрит стандарт, как это отрабатывает компилятор Microsoft и пр.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
21.05.2013, 00:06 38
Лучший ответ Сообщение было отмечено как решение

Решение

Цитата Сообщение от faridenco Посмотреть сообщение
Но, то что это не ошибка, а поведение зависит от реализации - это точно.
Поведение зависит от реализации — это implementation defined, на худой конец
unspecified behavior. А undefined behavior говорит о том, что реализации может вообще никакой не быть, то есть разработчику компилятора не стоит думать о поведении. Поведение непредсказуемо. Несколько запусков одной и той же программы могут давать разное поведение (но разумеется не обязаны).
Само использование "undefined behavior" — это и есть ошибка. Не синтаксическая, а семантическая.
5
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
21.05.2013, 00:07 39
Цитата Сообщение от faridenco Посмотреть сообщение
Вопрос был не только про компилятор, а про работу программы, уже скомпилированной (может ли она падать).
Цитата Сообщение от alsav22 Посмотреть сообщение
Как реагирует компилятор на такое освобождение неважно, в любом случае это ошибка.
Цитата Сообщение от Croessmah Посмотреть сообщение
На процесс компиляции это никак не повлияет - за такими вещами следит программист, а не компилятор.
Цитата Сообщение от Croessmah Посмотреть сообщение
Рано или поздно упадет, если, конечно же при компиляции Ваш код не был вырезан
Цитата Сообщение от taras atavin Посмотреть сообщение
По идее должна, так как эта же память потом будет освобождена ещё раз неявно, но винда врядли способна это гарантировать.
Вам еще на первой странице в один голос твердили, что упадет, что ошибка, что нельзя, но вы считаете себя умнее всех
0
0 / 0 / 0
Регистрация: 08.02.2013
Сообщений: 26
21.05.2013, 00:19  [ТС] 40
daslex, ЭТО НЕ ОШИБКА. Перечитай всю ветку и не тормози (или хотя бы мои сообщения).

Добавлено через 6 минут
Само использование "undefined behavior" — это и есть ошибка
Это означает, что поведение стандартом не определено.
И в этой ветке приводили примеры, когда один и тот же код с delete[] или вызывал оишбку или нет, в зависимости от реализации. Хотя по стандарту undefined behavior.
Есть величины размеры которых зависят от реализации, к ним употребляется термин implementation defined.
0
21.05.2013, 00:19
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.05.2013, 00:19
Помогаю со студенческими работами здесь

Освобождение памяти delete
Если у меня есть указатель (pt) N-ой степени, я присвоил ему указатель на начало массива (N - 1)ой...

Delete[] и утечка памяти
Как можно избежать вытока памяти? И вообще почкму криво работает? #include&lt;iostream&gt;...

Утечка памяти и delete
Вот накопились вопросы про утечки памяти. 1) Как проявляется утечка памяти? На многих сайтах...

Очистка памяти delete[];
Есть функция ввида: void loltest(int md3) { char* randChars; int cCount; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru