Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.65/17: Рейтинг темы: голосов - 17, средняя оценка - 4.65
0 / 0 / 0
Регистрация: 16.02.2009
Сообщений: 8

Ошибка удаления дин. массива AnsiString

16.02.2009, 11:49. Показов 3554. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Меня уже несколько лет приследует одна и та же проблема, которой я не могу найти решение.
Вкратце: при удалении динамического массива элементов AnsiString иногда возникает исключение "Access violation".
Более подробно это выглядит так:
Периодически возникает необходимость использовать массивы элементов, в каждом из которых есть AnsiString. Это может быть, как массив AnsiString, так массив структур, в которых есть тот же AnsiString. Для таких массивов я пишу объекты по принципу написал-отладил-зыбыл. После отладки объекта я продолжаю писать другие модули программы и вдруг ни с того, ни с сего возникает исключение на операторе delete в том самом отлаженном объекте, к которому я уже неделю не прикасаюсь. Промучившись с этим исключением два дня и ничего не решив я обычно плюю и за час переделываю все эти гребаные АнсиСтринги в char *. Только после этого я действительно забываю об объекте, потому что он начинает работать, как часы и, к тому же, быстрее. Проблема в том, что я не могу отловить эту ситуацию. Я не понимаю, почему это может происходить и как с этим бороться. Это происходит лишь иногда. Да, да! В это сложно поверить, я знаю, но жестко зафиксировать глюк не удается. Разговоры о "вылезании" за пределы выделенной памяти лишены всякого смысла, т.к. если бы у меня не было достаточно опыта, то с массивами char * я бы уж точно вылез за пределы, а с ними проблем нет. К примеру в одной из программ у меня было выделение памяти для 6 элементов AnsiString (число элементов было фиксировано константой, но массив был динамический - так было нужно). Как обычно в один прекрасные день это все захлебнулось в исключениях. После бессонной ночи я, так и не решив проблему, изменил 6 на 7 и все тут же заработало. Этот проект работает и развивается до сих пор все с той же семеркой и без глюков. Только что появилась возможность "поймать" глюк и я могу привести код, который у меня не работает. После трех нажатий на кнопку Button1 (вызов Button1Click(TObject *Sender) возникает исключение. Строка исключения помечена примечанием.

P.S. Код элементарный. Не поленитесь прочитать.
Конкретно этот код тестировался на бесплатном Turbo C++, но похожие ошибки возникали и на 5 и на 6 Builder'е.

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
 
struct SStruct{
 AnsiString Name;
 //any other defenitions
};
//---------------------------------------------------------------------------
 
class CClass{
 private:
  SStruct *Struct;
  int Size;
 public:
  void Add(AnsiString Name);
  void Clear();
  CClass();
  ~CClass();
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
 
void CClass::Add(AnsiString Name){
 SStruct *S=new SStruct[Size+1];
 for(int i=0;i<Size;i++)S[i]=Struct[i];
 if(Size)delete Struct; // Access violation
 S[Size++].Name=Name;
 Struct=S;
};
//---------------------------------------------------------------------------
 
void CClass::Clear(){
 if(Size)delete Struct;
 Size=0;
};
//---------------------------------------------------------------------------
 
CClass::CClass(){
 Size=0;
};
//---------------------------------------------------------------------------
 
CClass::~CClass(){
 Clear();
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
 
CClass *Class;
 
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
 Class=new CClass;
}
//---------------------------------------------------------------------------
 
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
 delete Class;
}
//---------------------------------------------------------------------------
 
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 Class->Add(Edit1->Name);
}
//---------------------------------------------------------------------------
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
16.02.2009, 11:49
Ответы с готовыми решениями:

из дин. дека в дин. стек (Borland С++)
Доброй ночи. Никак не получается сделать из динамического дека - стек. Помогите разобраться где...

Как перевести текст из AnsiString (в формате UTF8) в AnsiString формата Windows-1251?
Поиск по форуму не решил текущую проблему: 1. Есть текст в формате UTF-8 в величине: AnsiString...

Непонятная ошибка при инициализации дин. массива
Вылетает на memset'е с ошибкой записи. Что неправильно? int i = 0; int j = 0; int k = 0; ...

15
Любитель давать советы
 Аватар для Alexiski
342 / 135 / 14
Регистрация: 12.01.2009
Сообщений: 511
16.02.2009, 12:19
По стандарту положено писать
C++
1
delete[] Struct;
1
Почетный модератор
 Аватар для Lord_Voodoo
8785 / 2538 / 144
Регистрация: 07.03.2007
Сообщений: 11,873
16.02.2009, 12:26
а вы не пробывали юзать TStringList, в вашем случае он как раз подойдет...
0
0 / 0 / 0
Регистрация: 16.02.2009
Сообщений: 8
16.02.2009, 14:08  [ТС]
WooDooMan, обратите внимание на
Code
1
//any other defenitions
в объявлении структуры. В ней может быть куча всего другого. Тот код, который я привел максимально упрощен с сохранением структуры (в смысле структуры кода, а не структуры как типа). Кстати, TStringList в том проекте, где в последний раз проявился этот глюк, тоже есть

Alexiski, спасибо. Пишу на Си уже давно, но этого не видел ни разу. Я так понял квадратные скобки нужны, чтобы прога знала, что удаляется массив, а не один элемент. Если да, то возникает вопрос: неужели я каждый раз перед удалением памяти должен проверять размер массива и, в зависимости от результата проверки, использовать либо delete, либо delete[]?
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
16.02.2009, 14:19
Для массивов ты всегда обязан использовать квадратные скобки. Иначе память не освобождается.
Пишу на Си уже давно, но этого не видел ни разу
Значит, ты просто не читал книги по С++. Это есть в любой книжке или статье о выделении памяти.

Добавлено через 1 минуту 35 секунд
http://cplusplus.com/doc/tutorial/dynamic.html
0
0 / 0 / 0
Регистрация: 16.02.2009
Сообщений: 8
16.02.2009, 14:35  [ТС]
Цитата Сообщение от Vourhey Посмотреть сообщение
Значит, ты просто не читал книги по С++.
Почти все изучал сам.
Все-таки неясно, зачем эти скобки.
Во-первых, я так и не нашел ответа на свой предыдущий вопрос (если кто знает, подскажите), а во-вторых, из него вытекает еще один: если скобки указываются пустыми, значит компилятор (прога) знает размер массива. На хрена тогда их вообще указывать если прога знает его размер и может сама использовать delete для массивов длины 1 и delete[] для массивов длины >1?!

Добавлено через 1 минуту 27 секунд
P.S. Только что увидел ссылку. Читаю.
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
16.02.2009, 14:42
А откуда твоя прога узнает, что, память до этого была выделена для массива, а не для одного объекта? Ты и указываешь это. Отсюда и ответ на твои вопросы.
Почти все изучал сам.
Вот и зря
0
0 / 0 / 0
Регистрация: 16.02.2009
Сообщений: 8
16.02.2009, 14:56  [ТС]
Цитата Сообщение от Vourhey Посмотреть сообщение
А откуда твоя прога узнает, что, память до этого была выделена для массива, а не для одного объекта?
А массив из одного элемента не массив уже теперь?
И все-таки про мои вопросы Что, действительно проверять каждый раз? Т.е. какая разница между использованием этих двух операторов для особождения памяти, выделенной вот так:
C++
1
int *t=new int[1];
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
16.02.2009, 15:39
Да, блин, ничего не проверять! Если у тебя массив:
delete [размер(не обязательно)]
если не массив
delete

Добавлено через 3 минуты 7 секунд
А массив из одного элемента не массив уже теперь?
Очень остроумно и дико смешно. Где я сказал, что массив из одного элемента, не массив? Такой же массив, такой же пойнтер. Только на единственный элемент. Читай внимательней, что там по ссылке написано.
0
0 / 0 / 0
Регистрация: 16.02.2009
Сообщений: 8
16.02.2009, 15:40  [ТС]
__
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
16.02.2009, 15:51
Че до тебя никак не дойдет, что
C++
1
int *t=new int[10];
вернет тебе просто указатель на первый элемент: t[0]. Он вернет тебе просто int*. Откуда знать оператору delete, что ты ему передал указатель на первый элемент массива, а не просто указатель на int? Вот ты ему и указываешь, что int* это указатель только на первый элемент массива, а не на отдельный объект.

Добавлено через 9 минут 32 секунды
Yak, вообще если твоей логике следовать, то можно придраться к тому, что массив, на самом деле, не массив, а просто ряд объктов расположенных друг за другом в памяти. Ничего более...какой же это массив. А один элемент - это полюбому массив. Просто из одного элемента.
Ты что, думаешь на машинном уровне там массивы в памяти лежат? Ага, щас... Просто числа, без всяких индексов и т. д.. Просто числа в памяти. Напишу:
C++
1
2
int a=2;
int b=3;
и смело буду утверждать, что это массив. И еще обращусь к этим числам через индекс без проблем
Массив...не массив...
0
0 / 0 / 0
Регистрация: 16.02.2009
Сообщений: 8
16.02.2009, 15:53  [ТС]
Цитата Сообщение от Vourhey Посмотреть сообщение
Очень остроумно и дико смешно
Хреново, если смешно...

Там по ссылке написано, что надо так! И все, а почему - не ясно.
Разложу по полочкам:
То, что вы мне объяснили очень просто и понятно, а главное максимально доступно.
1. Если выделить память для 1 элемента (объекта), то освобождать ее надо без скобок.
2. Если выделить память для массива элементов, то освобождать ее надо со скобками.
Все просто. А если я выделил память для массива, но из одного элемента?! То как? Аааа, со скобками без скобок! ...или без скобками со скобок... Хммм...

Добавлено через 51 секунду
Можете уже не париться. Я нашел http://www.parashift.com/c++-f... #faq-16.13
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
16.02.2009, 15:53
все там написано, голову включи.
0
0 / 0 / 0
Регистрация: 16.02.2009
Сообщений: 8
16.02.2009, 16:04  [ТС]
Цитата Сообщение от Vourhey Посмотреть сообщение
Yak, вообще если твоей логике следовать, то можно придраться к тому, что массив, на самом деле, не массив, а просто ряд объктов расположенных друг за другом в памяти. Ничего более...какой же это массив. А один элемент - это полюбому массив. Просто из одного элемента.
Ты что, думаешь на машинном уровне там массивы в памяти лежат? Ага, щас... Просто числа, без всяких индексов и т. д.. Просто числа в памяти. Напишу:
Ну вот это уже более осмысленно, хотя и поздновато.
Ладно, все равно спасибо.

Добавлено через 2 минуты 46 секунд
P.S. Да, и над речью своей Вам следует поработать. Я вам все-таки не сосед.
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
16.02.2009, 16:14
А так как, я уже упоминал выше, что возвращается указатель на первый элемент, то массив из одного элемента, то удалить его я могу, как мне удобней. Хотя, правильней, в любом случае будет использовать [].

P. S. мне без разницы, сосед, не сосед. Русский тоже, вроде, правильный.
0
0 / 0 / 0
Регистрация: 16.02.2009
Сообщений: 8
17.02.2009, 09:36  [ТС]
Цитата Сообщение от Vourhey Посмотреть сообщение
то массив из одного элемента, то удалить его я могу
Цитата Сообщение от Vourhey Посмотреть сообщение
Русский тоже, вроде, правильный


Добавлено через 14 минут 9 секунд
Вчера потестил незамысловатую программу:
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
char ***C;
int a=100,b=1000,c=100;
 
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 C=new char**[a];
 for(int i=0;i<a;i++){
    C[i]=new char*[b];
    for(int k=0;k<b;k++)
       C[i][k]=new char[c];
 }
}
//---------------------------------------------------------------------------
 
void __fastcall TForm1::Button2Click(TObject *Sender)
{
 for(int i=0;i<a;i++){
    for(int k=0;k<b;k++)
       delete C[i][k];
    delete C[i];
 }
 delete C;
}
//---------------------------------------------------------------------------
 
void __fastcall TForm1::Button3Click(TObject *Sender)
{
 for(int i=0;i<a;i++){
    for(int k=0;k<b;k++)
       delete[] C[i][k];
    delete[] C[i];
 }
 delete[] C;
}
//---------------------------------------------------------------------------
Button2Click и Button3Click высвобождает одинаковое кол-во памяти с точностью до килобайта. Почему - не знаю. Видимо этого не знаю не я один. Потому что вразумительного объяснения никто не дал. Если следовать логике Vourhey, то оператор delete при удалении массива char *c=new char[1000] освободит 1 байт. На практике это не так.

P.S. Alexiski отдельное спасибо. Вопрос, озвученный в шапке темы решен с его помощью.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
17.02.2009, 09:36
Помогаю со студенческими работами здесь

Как увеличить размер дин. массива средствами С++
Привет всем!!! Подскажите плз, как увеличить размер (т.е добавить один элемент в конец)...

Работа с class ами. Заполнение дин. массива типа class
Всем доброго времени суток! Это моя первая тема на этом сайте, поэтому если что извините меня (за...

Крашится программа при попытке присваивания значения элементу дин-го массива
Не могу понять в чём ошибка. Я только учусь, поэтому возможно, что ошибка элементарная. Вот...

Добавление и удаление элементов дин массива
Задание: Создать класс «машина», имеющая марку, число цилиндров, мощность и цену. Определить...

Создание дин массива для структуры
программа для создания студентов и записывания их данных (фамилия оценка группа). структура: ...


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

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
Доступность команды формы по условию
Maks 07.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: сделать доступной кнопку (команда формы "ЗавершитьСписание") при. . .
Уведомление о неверно выбранном значении справочника
Maks 06.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "НарядПутевка", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если в документе выбран неверный склад. . .
Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt
8Observer8 05.04.2026
Среду разработки Qt Creator можно установить без фреймворка Qt. Есть отдельный репозиторий для этой среды: https:/ / github. com/ qt-creator/ qt-creator, где можно скачать установщик, на вкладке Releases:. . .
AkelPad-скрипты, структуры, и немного лирики..
testuser2 05.04.2026
Такая программа, как AkelPad существует уже давно, и также давно существуют скрипты под нее. Тем не менее, прога живет, периодически что-то не спеша дополняется, улучшается. Что меня в первую очередь. . .
Отображение реквизитов в документе по условию и контроль их заполнения
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеСпецтехники", разработанного в конфигурации КА2. Данный документ берёт данные из другого нетипового документа. . .
Фото всей Земли с борта корабля Orion миссии Artemis II
kumehtar 04.04.2026
Это первое подобное фото сделанное человеком за 50 лет. Снимок называют новым вариантом легендарной фотографии «The Blue Marble» 1972 года, сделанной с борта корабля «Аполлон-17». Новое фото. . .
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизитов табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: 1. Реализовать контроль заполнения реквизита. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru