Сейчас на форуме: zds (+5 невидимых) |
eXeL@B —› Программирование —› Затирание переменных, объявленных в куче |
Посл.ответ | Сообщение |
|
Создано: 19 февраля 2014 13:25 · Поправил: Wagos · Личное сообщение · #1 Добрый день. Проблема следующая - иногда при вызове библиотечных функций (MessageBox, ShowMessage и тд), а также - при динамическом выделении памяти (new, delete), затираются значения в структурах и массивах, также, объявленных в куче. Код не выкладываю, т. к. проект здоровый и затирание данных образуется в местах, никак не связанных друг с другом. Т. е. вызывается функция, в которой присутствуют вышеуказанные вызовы и после выполнения, к примеру, вызова TStringList* strList = new TStringList(); могут рандомно измениться значения в другой ранее объявленной структуре. Оперативной памяти с запасом. У кого-нибудь возникали подобные проблемы? Среда разработки: Embarcadero C++ Builder XE2. |
|
Создано: 19 февраля 2014 13:27 · Личное сообщение · #2 |
|
Создано: 19 февраля 2014 13:30 · Личное сообщение · #3 |
|
Создано: 19 февраля 2014 13:32 · Личное сообщение · #4 вам нужен отладчик использованой памяти выбирайте любой | Сообщение посчитали полезным: Wagos |
|
Создано: 19 февраля 2014 13:38 · Личное сообщение · #5 |
|
Создано: 19 февраля 2014 14:45 · Поправил: VodoleY · Личное сообщение · #6 Wagos могу сказать точно. в делфи/билдере очень большие проблемы с динамическим выделением памяти, часто все сыпится.. либо переписывайте код на статик переменные.. либо следите за стеком.. либо юзайте др. либу FastMM вроде.. типа альтернатива то... что происходит с динамическими переменными.. вообще шоу.. типа попробуйте сделать в цикле SetLength переменной .. массиву.. раз 50... с рандомным значением.. и прозреете ----- Наша работа во тьме, Мы делаем, что умеем. Мы отдаем, что имеем, Наша работа во тьме.... | Сообщение посчитали полезным: Wagos, dosprog |
|
Создано: 19 февраля 2014 15:53 · Поправил: Wagos · Личное сообщение · #7 |
|
Создано: 19 февраля 2014 16:15 · Личное сообщение · #8 |
|
Создано: 19 февраля 2014 16:19 · Личное сообщение · #9 Wagos ну давай логически.. MessageBox, ShowMessage в конце концов АПИ вызывают.. еслиб проблемы были в них.. сыпалась бы винда. если сыпяться они, значит не правильно кним параметры приходят.. самая первая проблема.. это гдето у тебя идет нескомпенсированный стек.. и этим функам приходит на вход мусор. ----- Наша работа во тьме, Мы делаем, что умеем. Мы отдаем, что имеем, Наша работа во тьме.... |
|
Создано: 19 февраля 2014 16:24 · Поправил: Wagos · Личное сообщение · #10 Dr0p, Самое забавное, что после удаления нескольких вызовов функций, проблемы исчезли (инструкции по выделению памяти работают корректно). Кстати, забыл, сказать - до этого была ещё одна проблема. Данные в динамической памяти менялись даже после простого вызова функции. В отладчике было видно, что после выполнения call'a (помещения в стек адреса возврата), шустро менялись некоторые переменные в структуре. Чем это объяснить, я не знаю. VodoleY, Это да, но функции корректно отрабатывают. Иначе бы я имел эксепшен, я думаю (в большинстве случаев). |
|
Создано: 19 февраля 2014 17:21 · Личное сообщение · #11 |
|
Создано: 19 февраля 2014 18:14 · Поправил: F_a_u_s_t · Личное сообщение · #12 Гейзенбаги довольно частое явление, падает в одном месте, ошибка совершенно в другом. Пользуйтесь логирами, что то типа eurekalog и какой нибудь утилитой для детекта утечек памяти. Скорее всего дело в инвалидных параметрах и стек\указатель летит к еб@ням. | Сообщение посчитали полезным: Wagos |
|
Создано: 19 февраля 2014 19:39 · Поправил: vden · Личное сообщение · #13 Wagos пишет: Момент затирания - в функции выделения памяти. Не понятно, почему она выделяет память в уже выделенной области. Скорее всего выделяет память правильно, а старая область уже освобождена. Указатель, естественно, неправильный. Лучше использовать FreeAndNil (обнулять указатель после освобождения класса), тогда будет легче найти обращение к NULL. |
|
Создано: 19 февраля 2014 20:06 · Личное сообщение · #14 |
|
Создано: 19 февраля 2014 21:22 · Поправил: dosprog · Личное сообщение · #15 Wagos, MessageBox() ничего не пишет, поэтому, думаю, не в самих аргументах дело. Попробуйте убрать всякую оптимизацию при компиляции, попробуйте другую версию того же компилятора... Правда, есть у меня старинная программка, так та глючит после компиляции на всей линейке MSVC 2..6, если не указать определённые опции компиляции (подбиралось втыком). Глючит при входе в одну из процедур. Я нашёл это место в .EXE - там явный косяк компилятора. Проявлялется похожим образом, как у вас. До сих пор у меня в makefile лежит пояснение: Code:
| Сообщение посчитали полезным: Wagos |
|
Создано: 19 февраля 2014 21:56 · Личное сообщение · #16 dosprog пишет: так та глючит после компиляции на всей линейке MSVC 2..6 Отладка студийных приложений и отладка делфи\билдер сильно отличается, во втором все проще из за информативности самого компилятора. Лично мне для отладки таких багов хватает EurekaLog и AQtime, остальную мелочь показывает сам компиль. В какой то версии студии был баг с разбором свитча, часть выкидывалось, нормально работало только с выключенным оптимизатором. Хотя такие баги компиля редкость, зачастую ошибки алгоритмические, если в цикле приходится выделять и освобождать память, то стоит пересмотреть алгоритм, так ли это обязательно, поскольку довольно дорогая операция и довольно легко сделать баги. У многих патологическое пристрастие экономить на спичках, при этом не замечая бревен. Часто вижу вопрос - какой выбрать алгоритм хеширования, что бы избежать коллизий ( хэши для файлов ), пилять, какая тут разница, если подсчет хэша ничто по сравнению с чтением файла в память. Это к тому, что иногда полезно пересмотреть алгоритмы, а не подпирать костылями из дефайнов и хаков. |
|
Создано: 19 февраля 2014 22:03 · Поправил: dosprog · Личное сообщение · #17 F_a_u_s_t, Билдер вообще меня доводил до исступления своими багами. Там их половина из-за ilink.exe. Поэтому лежит у меня BC 5.1 (не 5.2!) . А билдера нету вовсе. MSVC корректнее в разы работает, как трактор. Но бывают и там чудеса (как в примере выше). Согласен, что зачастую помогает исправление или изменение алгоритма. Всё это хорошо работает, если нет глюков при компиляции/трансляции. А у меня уже патологическая боязнь их. |
|
Создано: 19 февраля 2014 22:09 · Личное сообщение · #18 dosprog пишет: Билдер вообще меня доводил до исступления своими багами. Старого билдера уже нет, сейчас clang с хаками для vcl, которые по прежнему с багами, которые никто не правит, кроме комьюнити. Политика борланда\кодегира\эмбарко мне чем то напоминает политику Ильфака, с той лишь разницей, что в жопу не посылают прямым текстом, баглисты годами весят в неизменном виде и по большей части правятся компоненто писателями ( если VCL ), а так, появляются новые фичи, но толку с поддержки iOS если компилятор говно и приложение не пройдет ревью, фич много, а работает все через жопу, хороший пример хорошей идеи с хреновой реализацией. |
|
Создано: 20 февраля 2014 07:30 · Поправил: Wagos · Личное сообщение · #19 Установка FastMM результата не дала. CodeGuard молчит. Попробую что-нибудь увидеть с помощью Eurekalog (пока не получается включить опцию "утечки памяти", но решение есть). Ещё есть мысль использовать __fastcall'ы - попробую - отпишусь. Любопытства ради посмотрел через PEiD версию компилятора. "Borland C++ 1999". Может, конечно, подмена сигнатур, но иногда действительно кажется, что компилятор не обновлялся 15 лет. |
|
Создано: 20 февраля 2014 08:14 · Поправил: F_a_u_s_t · Личное сообщение · #20 Wagos пишет: Eurekalog (пока не получается включить опцию "утечки памяти", но решение есть). Статья Wagos пишет: Любопытства ради посмотрел через PEiD версию компилятора. "Borland C++ 1999". Сигнатура кривая, компилятор обновлялся, но кодогенератор это не особо затронуло, а в самом же компиляторе обновлений много, в первую очередь это поддержка стандарта, хотя сам компилятор старый, на базе Clang только x64 версия. Пруф: хоть бы свежим GCC собрали, версия 4.2 древняя, как говно мамонта. |
|
Создано: 21 февраля 2014 19:15 · Поправил: Wagos · Личное сообщение · #21 F_a_u_s_t, Спасибо за статью. Хорошая. Пока решил проблему уменьшением количества функций - скоро проект сдавать. Если ещё что-нибудь надумаю, напишу здесь. Цикл вызова функций (Класс TStringList): Create -> NewInstance -> GetMem -> FastGetMem (Функция FMM. Здесь, видимо, получается разрешение на использование ранее выделенной памяти) -> InitInstance (Окончательно забивается моя память всякой не нужной мне х@@нёй с помощью инструкции rep stosd). Ещё раз проштудировал код. Затираемый элемент находится в массиве структур, выделенный с помощью malloc и дальнейшим realloc (Векторы ненавижу, а для расширения массива не хотелось производить махинации с new - delete). Возможно, проблема в том, что данная память не заблокирована Виндой. Ещё одно наблюдение. При выделении памяти в конструкторе класса, все идет нормально. Если выделять память в методе данного класса, начинается волшебство. Увеличение размера кучи и стека - также не дало эффекта. Любит менеджер памяти выделять память в моей структуре. |
|
Создано: 23 февраля 2014 23:05 · Личное сообщение · #22 |
eXeL@B —› Программирование —› Затирание переменных, объявленных в куче |