Список форумов Шадринский форум -> Программирование -> Программирование для школьников и студентов. -> Выделение памяти
Начать новую тему   Ответить на тему   вывод темы на печать

Выделение памяти

Автор
Сообщение
moishe
Заслуженный писатель


Пол: Пол:Муж.
Зарегистрирован: 25.11.2004
Сообщения: 1668


Статус: Offline
СообщениеДобавлено: 2004.12.14 15:14.21
Ответить с цитатой
Сначала предисловие:
Пишу я программку одну, не важно, чего она там делает, главное, что в начале работы она всякую конфигурационную информацию из файлов считывает. Файлы текстовые и устроены однотипно - строки в виде <параметр>:<значение>. Я все это хозяйство в массивы запихиваю, состоящие из парных структур, ну, например
typedef struct {char *id; char *value;}
Потом массивы эти по первому полю сортирую, чтобы можно было быстренько бинарным поиском там что надо найти.
Раньше я память выделял только для собственно строковой информации, а массивы заводил декларативно, закладываясь на некий теоретический максимум. А теперь вот подумал: а чего это я память зря трачу, буду я под массивы тоже память динамически выделять. Ну и сделал сначала с realloc'ом, я ж не знаю, сколько у меня там элементов будет. Не пошло что-то. Программа выполняла недопустимую операцию и бывала закрыта. Ладно, пусть 2 прохода будет - информацию-то один раз только при старте надо считать, скорость большого значения не имеет. Считываю файл, пробегаю его, строки считаю, выделяю память сразу под весь массив, потом следующим проходом его заполняю.

А теперь проблема:
В первый раз - все ОК, работает, как и задумано. А вот при попытке выделить память для второго массива - падает. Что характерно, падает только под win98, ХР и 2000-я спокойно все проглатывают. Но мне надо, чтобы и под 98-й работало. Всяко попробовал, функции там такие-секие, опции компилятора тоже...

Теперь найденное решение:
Если выделять памяти не столько, сколько элементов в массиве реально окажется, а на один больше, все нормально работает и под win98. И я так кумекаю, что можно и realloc ставить, если только изначально запросить на один элемент больше.

Вопрос:
Почему?! Если кто знает, разъясните, пожалуйста.
Посмотреть профиль Отправить личное сообщение Отправить e-mail ICQ Number
xdsl
просто хороший человек


Пол: Пол:Муж.
Зарегистрирован: 25.11.2004
Сообщения: 1252
Откуда: shadrinsk

Статус: Offline
СообщениеДобавлено: 2004.12.14 16:13.03
Ответить с цитатой
Сишный компилятор чей? И версия какая?
Посмотреть профиль Отправить личное сообщение
moishe
Заслуженный писатель


Пол: Пол:Муж.
Зарегистрирован: 25.11.2004
Сообщения: 1668


Статус: Offline
СообщениеДобавлено: 2004.12.15 07:38.32
Ответить с цитатой
Borland C++ 5.5.1 из FreeCommandLineTools.
Это важно? Ведь я использую функции WinAPI, которые к компилятору не имеют отношения. IMHO, причина в механизмах выделения памяти.
Может быть что-нибудь подскажет сообщение: Программа вызвала сбой при обращении к странице памяти
в модуле KERNEL32.DLL по адресу 0187:bff7a125.
Строчка, вызывающая ошибку:
a=(gvIndex *)HeapAlloc(GetProcessHeap(),0,q*sizeof(gvIndex));
где q - честно подсчитанное количество будущих элементов, а gvIndex - это та самая структура из двух указателей (8 байт, я проверял). Соответственно, если вместо q написать q+1, все работает без ошибок. Гарантирую, что q вычислено правильно - это я в первую очередь проверил. К тому же на NT системах программа работает именно так, как ожидается.
Посмотреть профиль Отправить личное сообщение Отправить e-mail ICQ Number
moishe
Заслуженный писатель


Пол: Пол:Муж.
Зарегистрирован: 25.11.2004
Сообщения: 1668


Статус: Offline
СообщениеДобавлено: 2004.12.15 07:49.54
Ответить с цитатой
P.S.
Вместо HeapAlloc можно использовать LocalLock(LocalAlloc(...)) или malloc(), или calloc() - результат тот же. Хотя адрес в сообщении об ошибке вроде бы другой получается, не помню уже. Не пробовал VirtualAlloc - это немного из другой оперы, надо будет проверить. Неар'ы тоже пробовал разные брать - не помогает.
Посмотреть профиль Отправить личное сообщение Отправить e-mail ICQ Number
andy ice
Militärmagazinkatze


Пол: Пол:Муж.
Зарегистрирован: 25.11.2004
Сообщения: 23385


Статус: Offline
СообщениеДобавлено: 2004.12.15 08:56.38
Ответить с цитатой
moishe писал(а):
a=(gvIndex *)HeapAlloc(GetProcessHeap(),0,q*sizeof(gvIndex));
выделенное - это для чего?
_________________
Ин дер гросен фамилие нихт клювен клац-клац Neutral
Посмотреть профиль Отправить личное сообщение Отправить e-mail ICQ Number
moishe
Заслуженный писатель


Пол: Пол:Муж.
Зарегистрирован: 25.11.2004
Сообщения: 1668


Статус: Offline
СообщениеДобавлено: 2004.12.15 09:22.37
Ответить с цитатой
Это привычка, не более. На конечном коде не сказывается. Функция возвращает указатель на void, а я как бы "привожу" его к указателю на структуру. Хотя такие указатели компилятору и приводить-то не надо, так что это чисто для себя.
Посмотреть профиль Отправить личное сообщение Отправить e-mail ICQ Number
andy ice
Militärmagazinkatze


Пол: Пол:Муж.
Зарегистрирован: 25.11.2004
Сообщения: 23385


Статус: Offline
СообщениеДобавлено: 2004.12.15 10:04.22
Ответить с цитатой
не понятно, с чего бы выдавать ошибку при выделении памяти, ибо какая разница - 40 байт или 50 выделить?
_________________
Ин дер гросен фамилие нихт клювен клац-клац Neutral
Посмотреть профиль Отправить личное сообщение Отправить e-mail ICQ Number
moishe
Заслуженный писатель


Пол: Пол:Муж.
Зарегистрирован: 25.11.2004
Сообщения: 1668


Статус: Offline
СообщениеДобавлено: 2004.12.15 10:19.24
Ответить с цитатой
В том и фишка. Это явно не нехватка памяти - во-первых памяти еще полно, а во-вторых сам по себе отказ в выделении памяти не приводит к аварийному завершению процесса со стороны системы. К тому же первый раз память для массива выделяется, а второй раз - ошибка, хоть какого размера они будь, я разные комбинации пробовал.

Знал бы что там в KERNEL32 по адресу 0187:bff7a125 лежит, может и понял бы, почему ошибка.
Посмотреть профиль Отправить личное сообщение Отправить e-mail ICQ Number
moishe
Заслуженный писатель


Пол: Пол:Муж.
Зарегистрирован: 25.11.2004
Сообщения: 1668


Статус: Offline
СообщениеДобавлено: 2004.12.15 10:25.05
Ответить с цитатой
Это тем более странно, учитывая, что под строки память без проблем выделяется. Но я, правда, всегда для строки прошу на 1 байт больше, чем длина строки, чтобы нуль-терминатор туда записать. Такое впечатление, что массивам тоже некий терминатор нужен, причем только в 98-й почему-то. Сейчас попробую запросить не на 1 элемент, а на 1 байт больше...
Посмотреть профиль Отправить личное сообщение Отправить e-mail ICQ Number
moishe
Заслуженный писатель


Пол: Пол:Муж.
Зарегистрирован: 25.11.2004
Сообщения: 1668


Статус: Offline
СообщениеДобавлено: 2004.12.15 10:26.37
Ответить с цитатой
...работает!
Посмотреть профиль Отправить личное сообщение Отправить e-mail ICQ Number
vladislav
Запомнил кнопки...



Зарегистрирован: 04.02.2005
Сообщения: 147


Статус: Offline
СообщениеДобавлено: 2005.02.04 20:15.13
Ответить с цитатой
Ты знаешь, безсмысленно обсуждать, если нет перед глазами программы. У меня подозрение, что здесь элементарная алгоритмическая ошибка.
Посмотреть профиль Отправить личное сообщение
andy ice
Militärmagazinkatze


Пол: Пол:Муж.
Зарегистрирован: 25.11.2004
Сообщения: 23385


Статус: Offline
СообщениеДобавлено: 2005.02.04 20:20.58
Ответить с цитатой
мммм.... хы...
_________________
Ин дер гросен фамилие нихт клювен клац-клац Neutral
Посмотреть профиль Отправить личное сообщение Отправить e-mail ICQ Number
Страница 1 из 1
Начать новую тему   Ответить на тему   вывод темы на печать
Показать сообщения:   
Список форумов Шадринский форум -> Программирование -> Программирование для школьников и студентов. -> Выделение памяти

 
Перейти: 
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете вкладывать файлы
Вы можете скачивать файлы