|
Использование realloc() |
|
|
|
Jun 25 2009, 14:05
|
Профессионал
    
Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061

|
Здравствуйте! WinAVR 20071221. scmRTOS 3.05. ATmega48. Выделяю память в цикле (последовательно добавляю по одному байту). Код ... unsigned int* Buffer_Size; unsigned char* Buffer; ... // В цикле. (*Buffer_Size)++; Buffer = (unsigned char*) realloc((unsigned char*)Buffer, *Buffer_Size); ... При выделении на третьем байте realloc возвращает 0 почему? Память кончилась?  Благодарю заранее! Когда делаю, допустим, так: Код ... unsigned char* PBuff; ... PBuff = (unsigned char*) malloc(8); то всё нормально...
--------------------
Благодарю заранее!
|
|
|
|
|
Jun 26 2009, 06:15
|
Профессионал
    
Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061

|
Цитата(SysRq @ Jun 25 2009, 23:53)  Из такого куска кода как-то не ясно начальное значение (*Buffer_Size). Может быть действительно еще пара байт свободных байт остается... Перед началом выделения: Код *Buffer_Size = 0; Код ... unsigned char* PBuff; unsigned int Size_Buff; ... Res = USART.Read(PBuff, &Size_Buff); USART.Write(PBuff, Size_Buff); .... TStatus_Op TUSART_S::Read(unsigned char* Buffer, unsigned int* Buffer_Size) { unsigned char ParityBit; // Временная переменная для хранения значения 9-го бита принятого по USART байта данных. unsigned int i; unsigned char Event_Result;
Enable_RXD_Int(); // Разрешение прерывания по окончании передачи байта. *Buffer_Size = 0; i = 0; do { if (*Buffer_Size == 0) {Event_Result = ByteIsReceived_Event.Wait(0);} else {Event_Result = ByteIsReceived_Event.Wait(RD_TimeOut);};
if (!Event_Result) { // Тайм-аут при приёме байта. Disable_RXD_Int(); // Запрещение прерывания по окончании приёма байта. return SO_READ_TIME_OUT; }; (*Buffer_Size)++; Buffer = (unsigned char*) realloc((unsigned char*)Buffer, *Buffer_Size); // Выделение участка памяти. // Проверка успешности выделения участка памяти под буфер приёмника. if (!Buffer) { // Ошибка выделения участка памяти. Disable_RXD_Int(); // Запрещение прерывания по окончании приёма байта. return SO_MEMORY_NOT_ALLOCATED; }; ParityBit = Get_Parity_Bit(); // Извлечение очередного байта из регистра данных USART и загрузка его в буфер приёмника. *(Buffer + i) = Read_Byte(); i++; Enable_RXD_Int(); // Разрешение прерывания по окончании передачи байта. } while (*Buffer_Size < 7); Disable_RXD_Int(); // Запрещение прерывания по окончании приёма байта. return SO_OPERATION_COMPLETE; ... }; Памяти, я думаю, хватает... Следующий код работает нормально. Код ... unsigned char* PBuff; unsigned int Size_Buff; ... Size_Buff = 26; PBuff = (unsigned char*) malloc(Size_Buff); Res = USART.Read(PBuff, (const unsigned int) Size_Buff); USART.Write(PBuff, Size_Buff); free(PBuff); ... TStatus_Op TUSART_S::Read(unsigned char* Buffer, const unsigned int Buffer_Size) { unsigned char Event_Result;
for (unsigned int i = 0; i < Buffer_Size; i++) { Enable_RXD_Int(); // Разрешение прерывания по окончании передачи байта. if (i == 0) {Event_Result = ByteIsReceived_Event.Wait(0);} else {Event_Result = ByteIsReceived_Event.Wait(RD_TimeOut);}; if (!Event_Result) {return SO_READ_TIME_OUT;}; // Тайм-аут при приёме байта. // Извлечение очередного байта из регистра данных USART и загрузка его в буфер приёмника. *(Buffer + i) = Read_Byte(); }; return SO_OPERATION_COMPLETE; }; ... Смысл-то в том, чтобы менять размер буфера при приёме... Т. е., конечно, проще и надёжнее - выделить память под буфер на N байт сразу и прочитать эти N байт. А ещё проще и надёжнее - использовать обычный массив. А если N неизвестно или известно, что оно не более M? Выделять память по буфер M байт не хочется... неэкономично как-то и некрасиво  Программа работает совместно с scmRTOS. Так что процесс ждёт эвента ByteIsReceived_Event, свидетельствующего о получении байта по USART. Эвент сигналится в прерывании по приёму... Возможно, решение проблемы здесь: http://bytes.com/groups/c/603687-problem-reallocНадо проверить
--------------------
Благодарю заранее!
|
|
|
|
|
Jun 26 2009, 06:18
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(n_bogoyavlensky @ Jun 26 2009, 09:00)  Выделять память по буфер M байт не хочется... неэкономично как-то и некрасиво  Вы страшно далеки от представления, что такое realloc о его "'экономичности" и способах (отданных на откуп компилятору/системе) реализации и САМОЙ ВОЗМОЖНОСТИ сколь-нибудь хоть для чего-нибудь пригодной реализации на AVR. То, что Вы накропали с realloc это чистое безумие. Впрочем, все остальное не лучше  . Цитата При выделении на третьем байте realloc возвращает 0 почему? Память кончилась? Да, та минимальная порция (очевидно 4 байта в конкретной реализации), которую получили при первом запросе КОНЧИЛАСЬ.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 26 2009, 06:33
|
Профессионал
    
Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061

|
Цитата(zltigo @ Jun 26 2009, 09:18)  Вы страшно далеки от представления, что такое realloc о его "'экономичности" и способах (отданных на откуп компилятору/системе) реализации и САМОЙ ВОЗМОЖНОСТИ сколь-нибудь хоть для чего-нибудь пригодной реализации на AVR. Т. е., для AVRов realloc лучше вообще не использовать? Цитата То, что Вы накропали с realloc это чистое безумие. Ну, вроде всё правильно по книжке... На конкретные ляпы укажите, пожалуйста. Цитата Впрочем, все остальное не лучше  . Буду благодарен за комментарии и по поводу всего остального... Цитата Да, та минимальная порция (очевидно 4 байта в конкретной реализации), которую получили при первом запросе КОНЧИЛАСЬ. Что за минимальная порция? Можно немного поподробнее, пожалуйста?
--------------------
Благодарю заранее!
|
|
|
|
|
Jun 26 2009, 12:54
|
Профессионал
    
Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061

|
Цитата(SysRq @ Jun 26 2009, 11:45)  Значит zltigo прав. Разбирайтесь сколько отведено под heap и как он используется у вас в проекте...  Не понимаю. Ведь malloc работает! Та же самая куча... Я ей могу выделить сразу гораздо больший объём памяти!
--------------------
Благодарю заранее!
|
|
|
|
|
Jun 26 2009, 15:44
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(n_bogoyavlensky @ Jun 25 2009, 17:05)  При выделении на третьем байте realloc возвращает 0 почему? Память кончилась?  Весьма вероятно. Сделайте так: Код { void * a = malloc(0); void * b = malloc(0); printf("mcb size = %d", (uintptr_t)b - (uintptr_t) b); free(a); free(b); } Увидете, сколько занимает служебная информация (memory control block) в вашем менеджере памяти. Учтите, что каждый realloc() в общем случае выделяет блок нового размера и только после этого уничтожает старый. Т.е. для успешного завершения ему необходимо, чтобы в куче был свободный участок размером (новый размер + размер mcb). Еще один mcb на кучу возможно используется самим менеджером. Сколько вы выделили под кучу?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jun 29 2009, 06:08
|
Профессионал
    
Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061

|
Цитата(DpInRock @ Jun 26 2009, 18:16)  Я в Сях ничего не понимаю, но ради развлечения не увидел, в каком месте перед realloc выделяется начальный буфер. Realloc насколько я понимаю, просто изменяет размер уже существующего блока... avr-libc:Цитата It is acceptable to pass ptr as NULL, in which case realloc() will behave identical to malloc(). Т. е., если память изначально не выделена, то realloc() выделяет её подобно malloc(). Только вот указатель realloc() я передаю ненулевой... может в этом ещё дело... А так - это не просто безумие. Это даже для нормальных быстрых и замечательных процессорах с огромной памятью - безумие. Цитата В устройствах на всяких мелких процессорах без юзерскго интерфейса наличие ситуаций "нет памяти" просто безумна. Или если так приспичило "экономить", то проверять наличие памяти надо ДО приема. И соответтсвенно выставлять всякое разное для остановки потока данных (rts, там, DTR и прочая...). У меня функция ошибку возвращает, если памяти не хватило  Цитата(Сергей Борщ @ Jun 26 2009, 18:44)  Сколько вы выделили под кучу? Затрудняюсь ответить...  Кроме вызова realloc(), free() я ничего с памятью не делал... Нужно ещё как-то память под кучу выделить?
--------------------
Благодарю заранее!
|
|
|
|
|
Jun 29 2009, 08:16
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(n_bogoyavlensky @ Jun 29 2009, 09:08)  Только вот указатель realloc() я передаю ненулевой... может в этом ещё дело... Интересный подход. realloc() принимает указатель, который указывает на блок, выделенный при помощи malloc/realloc. Или NULL, тогда он действует как malloc. Если вы ему передаете указатель, содержащий что-либо другое - результат может быть любым, но только не выделением памяти. Вы поступаете как суровые русские мужики с японской лесопилкой. Цитата(n_bogoyavlensky @ Jun 29 2009, 09:08)  Затрудняюсь ответить...  Кроме вызова realloc(), free() я ничего с памятью не делал... Нужно ещё как-то память под кучу выделить? Уже не смешно. "Если уже ничего не помогает - прочтите, наконец, инструкцию". WinAVR\DOC\avr-libc\avr-libc-user-manual\malloc.html
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jun 29 2009, 08:30
|

Чайник, 1 литр
   
Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168

|
Гм. Я ж выше вам написал, что указатель проинициализировать надо, присвоив NULL. Вы отрапортавали что: Цитата(n_bogoyavlensky @ Jun 26 2009, 11:33)  Не помогло. Теперь же: Цитата(n_bogoyavlensky @ Jun 29 2009, 10:08)  Только вот указатель realloc() я передаю ненулевой... может в этом ещё дело... Не понятно, кроме того что не смешно
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|