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

Можно ли несколько раз делитить область памяти?

19.11.2011, 18:53. Показов 2860. Ответов 42
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Собственно, чреват ли ошибками код:
C++
1
2
3
4
5
6
7
8
int *a;
 
a = new int[2];
a[0] = 1;
a[1] = 2;
 
delete [] a;
delete [] a;
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.11.2011, 18:53
Ответы с готовыми решениями:

Копирование строки в область памяти несколько раз
Нужно скопировать строку str1 в str2 несколько раз, чтобы та размером в 50 бит заполнилась...

Сделать так, чтобы можно было добавить несколько одинаковых блюд, не кликая несколько раз
Ребята, подскажите! На форме2 надо сделать так, чтобы можно было добавить несколько одинаковых...

Можно ли в С++ выделить память под объект в заданную мной область памяти?
Есть код static inline void convertFromTextAlternative(quint8* dst, const QVariant& src){ ...

Можно ли создать нераспределенную область памяти если диск С занял все место?
Всем привет! есть вопросик: можно ли создать нераспределенную область памяти если диск С занял все...

42
5 / 5 / 0
Регистрация: 28.11.2010
Сообщений: 81
19.11.2011, 19:45  [ТС] 21
Author24 — интернет-сервис помощи студентам
Собственно, попробовал запустить этот код, компилятор (Qt'шный) не стал ругаться, программа отработала корректно.
Так где собака то зарыта?
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
19.11.2011, 19:51 22
Svinina, нигде, код абсолютно корректный
0
5 / 5 / 0
Регистрация: 28.11.2010
Сообщений: 81
19.11.2011, 19:53  [ТС] 23
Ну Берс в самом начале написал, что такой код чреват ошибками.
Вот и интересуюсь, какими=)
1
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
19.11.2011, 19:54 24
Цитата Сообщение от Bers Посмотреть сообщение
Нет никакой гарантии, что NULL - это ноль.
Есть гарантия, что NULL - это невалидный спецадрес, обозначающий, что указатель ни куда не указывает. И усматривают здесь изготовители не компиляторов, всё зависит от начального адреса памяти. На IBM совместимых это должен быть ноль, не зависимо от компиляторов и даже от языков, а сигнальные камни любят память с ноля начинать, а если так сделано, то NULL не имеет права быть нолём, опять таки даже в том случае, если кроскомпилятор прошивок таких коммутаторов выпустит мелкософт.
0
Заблокирован
19.11.2011, 19:57 25
Цитата Сообщение от Svinina Посмотреть сообщение
Ну Берс в самом начале написал, что такой код чреват ошибками.
Вот и интересуюсь, какими=)

Первый раз delete освобождает память. С этого момента, этот кусок памяти становится "свободным". И система в любой миг может отдать его ещё кому нибудь.

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

Добавлено через 55 секунд
taras atavin, да я уже вразумел)

NULL всегда не_валидный адрес, но не всегда является нулём)
2
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
19.11.2011, 19:58 26
Цитата Сообщение от Jupiter Посмотреть сообщение
в Си NULL это ноль приведенный к void* в C++ NULL это ноль
Не ноль, а невалидный номер байта. На IBM совместимых гарантировано невалидный номер байта - это ноль, но если сдеать c, или c++ кроскомпилятор для сиганального камня, то там может быть и другое значение NULL.
0
Заблокирован
19.11.2011, 20:00 27
Цитата Сообщение от taras atavin Посмотреть сообщение
Не ноль, а невалидный номер байта.
Именно ноль, и если я правильно понял, именно из-за этого и был принят nullptr
(что бы различать int равный нулю и void* равный нулю)
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
19.11.2011, 20:01 28
Цитата Сообщение от Bers Посмотреть сообщение
Говорят: пиши тогда уж просто ноль. Так будит безопаснее.
Опаснее. И именно потому, что NULL - это не всегда ноль.
0
Jupiter
19.11.2011, 20:25
  #29

Не по теме:

Цитата Сообщение от Bers Посмотреть сообщение
Второй раз delete пытается освободить уже чужую память. И если эта память принадлежит уже кому то там - может произойти порча данных (хотя скорее всего система этот косяк пофиксит, и заломает накосячевший процесс)
таки Bers прав:), признаю свою ошибку в 22 посту

0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
19.11.2011, 20:40 30
Цитата Сообщение от Bers Посмотреть сообщение
Гарантированно оно, если delete []a; a=0;
Не?
А если дефайн - никаких гарантий нет.
Наоборот. Если NULL!=0, то по
C++
1
2
a=0;
delete [a];
очень даже произойдёт. А если дефайном, то вопрос только в правильности дефайна, ну так не пользуйся не правильным и при любом значении NULL ничего не произойдёт. Кстати, я никогда не полагаюсь на проверку внутри delete, а всегда пишу явно
C++
1
2
3
4
if (p)
{
 delete [] p;
}
0
Заблокирован
19.11.2011, 20:41 31
Я такую запись не понимаю:
Цитата Сообщение от taras atavin Посмотреть сообщение
delete [a];
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
19.11.2011, 21:04 32
Цитата Сообщение от Bers Посмотреть сообщение
не сказать, что хорошо знаю стандарт, но помойму, там идёт проверка на ноль, а не на NULL
На значение NULL без обращения упоминания имени данного макроса, так как проверять просто на ноль нельзя: если ноль - валидный адрес, то это может привести к невозможности выделить память.

Добавлено через 13 минут
Цитата Сообщение от Bers Посмотреть сообщение
Первый раз delete освобождает память. С этого момента, этот кусок памяти становится "свободным". И система в любой миг может отдать его ещё кому нибудь.
Второй раз delete пытается освободить уже чужую память. И если эта память принадлежит уже кому то там - может произойти порча данных
. Нет. Ни каких чужих данных там быть не может: в многозадачных осях все программы работают в виртуальных адресных пространствах, а освобожденная память из них изымается, то есть виртуальный адрес после освобождения становится столь же невалидным, как и NULL, кусок же памяти по тому же физическому адресу, который как раз может быть выдан кому то ещё, после такого выделения окажется в другом виртуальном адресном пространстве, так как они все локальны, глобальны только физические адреса, а в однозадачной системе просто больше никого нет, кому могла бы быть выдана память по тому же адресу. Опасно же второй раз удалять не подряд, если та же самая прога и тот же её екземпляр успеет получить кусок памяти, на который попадёт тот же адрес.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
... f1(...)
{
 static ... *p;
 ...
 p=new ...;
 ...
 delete [] *p;  // Эта строчка выполнилась дважды в разные вызовы f1, а между ними p попал в память выданную f2
}
... f2(...)
{
 static ... *p;
 ...
 p=new ...; 
 ...
 delete [] *p;
}
. И всё таки дважды делитить можно в единственном случае: если между делитами было ещё одно выделение памяти с того же начального адреса.

Добавлено через 4 минуты
То есть
C++
1
2
3
4
5
6
7
8
int *p;
p=new int [...];
...
delete [] p;
...
p=new int [...];
...
delete [] p;
можно.
0
5 / 5 / 0
Регистрация: 28.11.2010
Сообщений: 81
19.11.2011, 21:08  [ТС] 33
в многозадачных осях все программы работают в виртуальных адресных пространствах, а освобожденная память из них изымается, то есть виртуальный адрес после освобождения становится столь же невалидным, как и NULL
А вот тут можно поподробнее?
Правильно ли я понимаю, что один раз выделив память, а затем ее освободив, физически к этой области памяти процесс уже доступа получить никогда не сможет?
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
19.11.2011, 21:17 34
Цитата Сообщение от Bers Посмотреть сообщение
Именно ноль, и если я правильно понял, именно из-за этого и был принят nullptr
Нет. Имплементейшн дефайн - это как раз и есть не всегда ноль. А nullptr приняли, чтоб избавиться от макроса в неконтролируеммом заголовке. У меня где то был исходник для убунты, начинающийся с
C++
1
#define NULL 0
, дефайн этот я написал собственноручно, так вот, если такое начало будет в исходнике для сигнального камня, то получим полную фигню. Компилятор и так должен соответствовать архитектуре, не только по значению NULL, а дефайн может быть в любом "левом" заголовке и даже прямо в исходнике, автор которого архитектуру мог не только не учитывать, а ещё и делать для другой архитектуры. Константа же, известная самому компилятору, а не препроцессору, не будет зависеть от таких самодельных дефайнов, а только от компилятора.

Добавлено через 4 минуты
Цитата Сообщение от Bers Посмотреть сообщение
delete [a];
Я тоже эту очепятку не понимаю. Должно быть
C++
1
delete [] a;
0
Заблокирован
19.11.2011, 21:18 35
taras atavin,
C++
1
2
3
4
5
6
7
void Foo(int a) {...}
void Foo( void* ptr) {...}
 
...
 
Foo(0); //угадай, какая из функций будит запущена?
           //если угадаешь правильно, поймёшь, зачем нужен nullptr_t
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
19.11.2011, 21:26 36
Цитата Сообщение от Svinina Посмотреть сообщение
А вот тут можно поподробнее?
Правильно ли я понимаю, что один раз выделив память, а затем ее освободив, физически к этой области памяти процесс уже доступа получить никогда не сможет?
Почему "никогда"? К этой памяти можно обратиться, если:
1. Освобождённый адрес находится на странице, содержащей другой, валидный локальный адрес. В этом случае освобожденный адрес тоже должен стать невалидным, но система не в состоянии этого гарантировать. Но память на одной странице не может быть выдана разным процессам, так что чужую память ты таким образом не освободишь и к ней не обратишься.
2. Если память была повторно выделена процессу.

Добавлено через 2 минуты
Цитата Сообщение от Bers Посмотреть сообщение
void Foo(int a) {...}
void Foo( void* ptr) {...}
...
Foo(0); //угадай, какая из функций будит запущена?
* * * * * *//если угадаешь правильно, поймёшь, зачем нужен nullptr_t
C++
1
2
3
4
5
#define NULL 0xFFFF
void Foo(int a) {...}
void Foo( void* ptr) {...}
...
Foo(0); //А здесь? Если NULL дефайнить числом, то и здесь проблема та же, дело не в ноле.
Это ещё одна цель введения nullptr.
0
Заблокирован
19.11.2011, 21:29 37
Цитата Сообщение от taras atavin Посмотреть сообщение
Foo(0); //А здесь?
Константа не_ноль интерпритируется как инт по умолчанию. Естественно первый вариант
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
19.11.2011, 21:47 38
Цитата Сообщение от Bers Посмотреть сообщение
Естественно первый вариант
Первый и должен, так как аргумент - число. Но и NULL - тоже число, то есть foo(NULL) вызовет первый вариант, а программист имеет ввиду второй. Если аргумент - переменная указательного типа, то вызовется второй вариант, как и должно быть. Целей может быть много, но в данном случае на самом деле всё таки одна - избавиться от макроса. Почему надо от него избавиться - это уже другой вопрос и проблема со многими аспектами. Возможность ошибочного дефайна - один из них. Второй - вызов перегруженной функции с невалидным указателем, если есть версия c интом. Чтоб не писать
C++
1
2
int *p=NULL;
foo(p);
. Кстати, а как будет здесь:
C++
1
2
3
4
5
6
7
#define NULL (void*)0xFFFF
void foo(int x);
void foo(void *p);
void foo(int *p);
...
foo(0);
foo(NULL);
и здесь:
C++
1
2
3
4
5
6
void foo(int x);
void foo(void *p);
void foo(int *p);
...
foo(0);
foo(nullptr);
? Валидные указаетели все имеют типы, так как являются переменными. Указатель-переменная с невалидным значением тоже имеет тип. А как быть с nullptr? Ведь программист может под этой константой подразумевать невалидный указатель на что угодно, причём ещё и не всегда одно и тоже в разных местах программы.
0
Заблокирован
19.11.2011, 21:48 39
Цитата Сообщение от taras atavin Посмотреть сообщение
А как быть с nullptr?
эта волшебная константа типа nullptr_t
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
19.11.2011, 21:51 40
Кстати, студия 2008 не знает ни nullptr, ни NULL_PTR, ни null_ptr, ни NULLPTR.
0
19.11.2011, 21:51
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.11.2011, 21:51
Помогаю со студенческими работами здесь

Можно ли использовать несколько раз setlocale? Если да, то как?
Можно ли использовать несколько раз setlocale? Если да, то как ?Мне это нужно только лишь потому,...

Можно ли восстановить несколько раз отредактированный документ microsoft word?
Цель: восстановить в начальное состояние отредактированный(несколько раз открывался, изменялся и...

Можно ли, проделав эту операцию несколько раз, получить число более 10 000?
На доске записано натуральное число n, 1000 < n < 3000. Вася может прибавить к числу произведение...

Как можно уменьшить код если его куски повторяются по несколько раз?
Здравствуйте. Как можно уменьшить код если его куски повторяются по несколько раз? Для функций это...


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

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