Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Странное поведение менеджера кучи 
:(
    Опции темы
En_t_end
Дата 27.6.2005, 11:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2074
Регистрация: 4.12.2004

Репутация: 1
Всего: 20



Очень странно вести себя стал smile
Допустим есть...
char **test = new char*[MAX_TEST];
for(unsigned long i = 0; i <= MAX_TEST; i++)
test[i] = new char[MAX_LONG_TEST+1];

Чтобы освободить память xочу испоьзовать...
for(unsigned long i = 0; i <= MAX_TEST; i++)
delete[] test[i];
delete[] test;
Но программа при выполнении освобождения памяти почему-то сообщает о фатальной ошибке. ЗЫ нигде больше памятью test не управлял, поэтому грешить на удаление несуществующих членов не приходиться.
Да к тому же вот это работает:
delete[] test[0];
delete[] test[MAX_TEST];
delete[] test;

Это сообщение отредактировал(а) En_t_end - 27.6.2005, 11:57
PM MAIL ICQ Skype GTalk Jabber   Вверх
comcon1
Дата 27.6.2005, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 838
Регистрация: 11.6.2005
Где: Москва ДАС-МГУ

Репутация: 12
Всего: 17



Че-то я не втыкаю, почему ты удаляешь test[i] оператором delete[]. Ведь создаешь ты (char*) так:
Код

char *_string = new char[30];
// а удаляешь
delete _string;

ведь __string - не массив указателей, чтобы удалять ее delete[].


--------------------
PM MAIL   Вверх
Earnest
Дата 27.6.2005, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Было бы странно, если бы фатальной ошибки не было...

Код

char **test = new char*[MAX_TEST];
for(unsigned long i = 0; i <= MAX_TEST; i++)
test[i] = new char[MAX_LONG_TEST+1];


Вы выделяете MAX_TEST кусков памяти, а потом записываете в них MAX_TEST+1 указателей. Элемент с индексом MAX_TEST (test[MAX_TEST]) - незаконный. Программа валится на освобождении памяти, т.к. сама по себе запись в чужую память редко сразу приводит к фатальным последствиям.

commom1
Формально, любой массив можно (нужно) удалять оператором delete[]. При этом компилятор вызывает деструктор для каждого элемента массива. Но в данном случае это, действительно, не обязательно, хотя вполне законно написано. А для массива указателей вызывать delete[] как раз бесполезно: delete для каждого элемента вызван не будет - это ответственность программиста - любишь вызывать new, люби и саночки возить... Или пользуйся smart-указателями.

Это сообщение отредактировал(а) Earnest - 27.6.2005, 12:59


--------------------
...
PM   Вверх
pablo
Дата 27.6.2005, 12:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 12.2.2005
Где: Вильнюс, Литва

Репутация: 4
Всего: 6



только что проверил твой код, он оказывается абсолютно рабочий, ищи ошибку в другом месте.

Вот код:
Код
#include <iostream>

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

#define MAX_TEST 10
#define MAX_LONG_TEST 11

int main()
{
    char **test = new char*[MAX_TEST];
    for(unsigned long i = 0; i <= MAX_TEST; i++)
        test[i] = new char[MAX_LONG_TEST+1];

    for(unsigned long i = 0; i <= MAX_TEST; i++)
        delete[] test[i];
    delete[] test;
    system("pause");
    return 0;
}



--------------------
Первый блин всегда похож на сферу, иногда бывает и куб.
PM MAIL ICQ   Вверх
Earnest
Дата 27.6.2005, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Да вы что, господа, какой рабочий! Валится или не валится - это уж как повезет. Причем везет - это когда валится сразу.
Но выделить MAX_TEST элементов, а заполнять MAX_TEST+1 - это, по-вашему, нормально?


--------------------
...
PM   Вверх
pablo
Дата 27.6.2005, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 12.2.2005
Где: Вильнюс, Литва

Репутация: 4
Всего: 6



Извините не заметил, надо просто в циклах убрать снак равенства и всё будет в ажуре. smile


--------------------
Первый блин всегда похож на сферу, иногда бывает и куб.
PM MAIL ICQ   Вверх
En_t_end
Дата 27.6.2005, 15:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2074
Регистрация: 4.12.2004

Репутация: 1
Всего: 20



Earnest
Тогда покажи пример с char**, где бы память выделялась и освобождалась правильно.
PM MAIL ICQ Skype GTalk Jabber   Вверх
Earnest
Дата 27.6.2005, 15:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Pablo уже написал - замени в циклах "<=" на "<" и все будет правильно.
Цикл у тебя сколько раз выполняется? Правильно, MAX_TEST+1 раз.
Последний элемент, который ты инициализируешь в цикле - это test[MAX_TEST]. Неважно, что ты туда пишешь - не имешь права, т.к. этого элемента нет.

Это сообщение отредактировал(а) Earnest - 27.6.2005, 15:27


--------------------
...
PM   Вверх
ManiaK
Дата 27.6.2005, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Homo Sapience
***


Профиль
Группа: Комодератор
Сообщений: 1145
Регистрация: 3.8.2004
Где: ИУ5-93

Репутация: 5
Всего: 29



Earnest согласен. Жульничают smile

Насчёт:
Цитата(Earnest @ 27.6.2005, 13:51)
Формально, любой массив можно (нужно) удалять оператором delete[].

Цитата(Earnest @ 27.6.2005, 13:51)
А для массива указателей вызывать delete[] как раз бесполезно

По-хорошему всегда нужно удалять массив оператором delete[]. Даже в приведённом примере никто не гарантирует, что через какое-то время программу достанут и добавят какую-нибудь новую фичу, использующую переопределённые операторы new, new[], delete, delete[] в глобальной области. Насколько помню, могут быть немаленькие казусы и, главное, вы сначала порвёте все волосы у себя на голове и только потом поймёте, что вы сделали не так.
PM MAIL WWW   Вверх
En_t_end
Дата 27.6.2005, 15:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2074
Регистрация: 4.12.2004

Репутация: 1
Всего: 20



Earnest
delete[] test[MAX_TEST]; почему тогда это работает ?
PM MAIL ICQ Skype GTalk Jabber   Вверх
ManiaK
Дата 27.6.2005, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Homo Sapience
***


Профиль
Группа: Комодератор
Сообщений: 1145
Регистрация: 3.8.2004
Где: ИУ5-93

Репутация: 5
Всего: 29



Цитата(En_t_end @ 27.6.2005, 16:26)
delete[] test[MAX_TEST]; почему тогда это работает ?

Насколько понимаю, удаляется массив указателей - и удаляется он верного размера. А вот если попытаться удалить элемент MAX+1 в нём - то будут проблемы, т.к. этого элемента не существует.
PM MAIL WWW   Вверх
B2_Russia
Дата 27.6.2005, 15:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


В доску свой :)
**


Профиль
Группа: Участник
Сообщений: 344
Регистрация: 3.7.2003
Где: Тверь

Репутация: нет
Всего: 1



Цитата(En_t_end @ 27.6.2005, 11:55)
Очень странно вести себя стал smile
Допустим есть...
char **test = new char*[MAX_TEST];
for(unsigned long i = 0; i <= MAX_TEST; i++)
test[i] = new char[MAX_LONG_TEST+1];

Чтобы освободить память xочу испоьзовать...
for(unsigned long i = 0; i <= MAX_TEST; i++)
delete[] test[i];
delete[] test;
Но программа при выполнении освобождения памяти почему-то сообщает о фатальной ошибке. ЗЫ нигде больше памятью test не управлял, поэтому грешить на удаление несуществующих членов не приходиться.
Да к тому же вот это работает:
delete[] test[0];
delete[] test[MAX_TEST];
delete[] test;

Попробуй так:

for(unsigned long i = 0; i <= MAX_TEST; i++)
delete[] test[i];
delete[] (char*)test;

Короче может быть чтото с несоответствием типов

PM WWW ICQ   Вверх
Earnest
Дата 27.6.2005, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



En_t_end
А это тебе кажется, что работает. Не повезло, значит. smile
Имей в виду, что неправильный код рано или поздно стукнет. Причем в совершенно неожиданном месте. И искать такую ошибку ты можешь ох как долго.

Почему сразу не валится, это еще и от компилятора зависит. Например, VC в отладочном режиме специально помечает память, выделенную new - а потом при освобождении проверяет, освобождаешь ли ты то, что выделил. Так что с этой точки зрения все, как кажется, нормально. Выделил указатель - освободил указатель. То, где хранится этот указатель, в данном случае не срабатывает - ты просто больше не трогаешь эту память.
Вполне вероятно, что память сразу за массивом test выделяется для какого-то из массивов test[i]. Я думаю, если ты пройдешься по своей программе отладчиком и последишь за значениями переменных, увидишь много интересного. Скорее всего, содержимое ячейки test[MAX_TEST] изменяется во время одного из освобождений. А потом ты вызываешь для нее delete...

Это сообщение отредактировал(а) Earnest - 27.6.2005, 15:46


--------------------
...
PM   Вверх
En_t_end
Дата 27.6.2005, 15:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2074
Регистрация: 4.12.2004

Репутация: 1
Всего: 20



B2_Russia
Попробывал(предварительно в циклах убрал <= на <(это верно, просто я ступил smile)) Все равно - ошибка smile. Может это у моей системы крыша едет ?
PM MAIL ICQ Skype GTalk Jabber   Вверх
ManiaK
Дата 27.6.2005, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Homo Sapience
***


Профиль
Группа: Комодератор
Сообщений: 1145
Регистрация: 3.8.2004
Где: ИУ5-93

Репутация: 5
Всего: 29



А чему равна константа MAX_TEST если не секрет?
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1881 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.