реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Использование realloc()
koluna
сообщение Jun 25 2009, 14:05
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 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 почему?
Память кончилась? smile.gif

Благодарю заранее!

Когда делаю, допустим, так:
Код
...
unsigned char* PBuff;
...
PBuff = (unsigned char*) malloc(8);

то всё нормально...


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
SysRq
сообщение Jun 25 2009, 20:53
Сообщение #2


Чайник, 1 литр
****

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



Из такого куска кода как-то не ясно начальное значение (*Buffer_Size). Может быть действительно еще пара байт свободных байт остается...
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 26 2009, 06:15
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 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 байт не хочется... неэкономично как-то и некрасиво smile.gif

Программа работает совместно с scmRTOS.
Так что процесс ждёт эвента ByteIsReceived_Event, свидетельствующего о получении байта по USART.
Эвент сигналится в прерывании по приёму...

Возможно, решение проблемы здесь: http://bytes.com/groups/c/603687-problem-realloc
Надо проверить smile.gif


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 26 2009, 06:18
Сообщение #4


Гуру
******

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



Цитата(n_bogoyavlensky @ Jun 26 2009, 09:00) *
Выделять память по буфер M байт не хочется... неэкономично как-то и некрасиво smile.gif

Вы страшно далеки от представления, что такое realloc о его "'экономичности" и способах (отданных на откуп компилятору/системе) реализации и САМОЙ ВОЗМОЖНОСТИ сколь-нибудь хоть для чего-нибудь пригодной реализации на AVR. То, что Вы накропали с realloc это чистое безумие. Впрочем, все остальное не лучше sad.gif.
Цитата
При выделении на третьем байте realloc возвращает 0 почему?
Память кончилась?

Да, та минимальная порция (очевидно 4 байта в конкретной реализации), которую получили при первом запросе КОНЧИЛАСЬ.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 26 2009, 06:33
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(zltigo @ Jun 26 2009, 09:18) *
Вы страшно далеки от представления, что такое realloc о его "'экономичности" и способах (отданных на откуп компилятору/системе) реализации и САМОЙ ВОЗМОЖНОСТИ сколь-нибудь хоть для чего-нибудь пригодной реализации на AVR.


Т. е., для AVRов realloc лучше вообще не использовать?

Цитата
То, что Вы накропали с realloc это чистое безумие.


Ну, вроде всё правильно по книжке... На конкретные ляпы укажите, пожалуйста.

Цитата
Впрочем, все остальное не лучше sad.gif.


Буду благодарен за комментарии и по поводу всего остального...

Цитата
Да, та минимальная порция (очевидно 4 байта в конкретной реализации), которую получили при первом запросе КОНЧИЛАСЬ.


Что за минимальная порция?
Можно немного поподробнее, пожалуйста?


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
SysRq
сообщение Jun 26 2009, 06:44
Сообщение #6


Чайник, 1 литр
****

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



Попробуйте инициализировать PBuff (присвоить NULL), а вызов realloc загоните в критическую секцию (в scmRTOS должны быть средства).
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 26 2009, 07:33
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(SysRq @ Jun 26 2009, 09:44) *
Попробуйте инициализировать PBuff (присвоить NULL), а вызов realloc загоните в критическую секцию (в scmRTOS должны быть средства).


Не помогло.


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
SysRq
сообщение Jun 26 2009, 08:45
Сообщение #8


Чайник, 1 литр
****

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



Значит zltigo прав. Разбирайтесь сколько отведено под heap и как он используется у вас в проекте... unsure.gif
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 26 2009, 12:54
Сообщение #9


Профессионал
*****

Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061



Цитата(SysRq @ Jun 26 2009, 11:45) *
Значит zltigo прав. Разбирайтесь сколько отведено под heap и как он используется у вас в проекте... unsure.gif


Не понимаю.
Ведь malloc работает! Та же самая куча...
Я ей могу выделить сразу гораздо больший объём памяти!


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Jun 26 2009, 15:16
Сообщение #10


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



Я в Сях ничего не понимаю, но ради развлечения не увидел, в каком месте перед realloc выделяется начальный буфер.
Realloc насколько я понимаю, просто изменяет размер уже существующего блока...

А так - это не просто безумие. Это даже для нормальных быстрых и замечательных процессорах с огромной памятью - безумие.

В устройствах на всяких мелких процессорах без юзерскго интерфейса наличие ситуаций "нет памяти" просто безумна.
Или если так приспичило "экономить", то проверять наличие памяти надо ДО приема. И соответтсвенно выставлять всякое разное для остановки потока данных (rts, там, DTR и прочая...).


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 26 2009, 15:44
Сообщение #11


Гуру
******

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



Цитата(n_bogoyavlensky @ Jun 25 2009, 17:05) *
При выделении на третьем байте realloc возвращает 0 почему?
Память кончилась? smile.gif
Весьма вероятно. Сделайте так:
Код
{
    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)
Go to the top of the page
 
+Quote Post
koluna
сообщение Jun 29 2009, 06:08
Сообщение #12


Профессионал
*****

Группа: Участник
Сообщений: 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 и прочая...).


У меня функция ошибку возвращает, если памяти не хватило smile.gif

Цитата(Сергей Борщ @ Jun 26 2009, 18:44) *
Сколько вы выделили под кучу?


Затрудняюсь ответить... sad.gif
Кроме вызова realloc(), free() я ничего с памятью не делал...
Нужно ещё как-то память под кучу выделить?


--------------------
Благодарю заранее!
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Jun 29 2009, 06:57
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Цитата(n_bogoyavlensky @ Jun 29 2009, 10:08) *
У меня функция ошибку возвращает, если памяти не хватило smile.gif


1. Вы же не сидите внутри вашего устройства. Кто (что) и каким образом будет реагировать на этот код ошибки?
2. Realloc - большое зло. Чем быстрее вы его изгоните из своей программы, тем лучше.
3. Если уж совсем в лом разбираться с размером heap (хотя, скорее всего в startup модуле есть соответствующий параметр) напишите простенький цикл с malloc(1), и быстро поймете размер кучи. Не забывайте про этом, что вам уже писали коллеги - у каждого выделенного блока есть еще накладные расходы в виде доп. байт на модуль.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 29 2009, 08:16
Сообщение #14


Гуру
******

Группа: Модераторы
Сообщений: 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) *
Затрудняюсь ответить... sad.gif
Кроме вызова 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)
Go to the top of the page
 
+Quote Post
SysRq
сообщение Jun 29 2009, 08:30
Сообщение #15


Чайник, 1 литр
****

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



Гм. Я ж выше вам написал, что указатель проинициализировать надо, присвоив NULL.
Вы отрапортавали что:
Цитата(n_bogoyavlensky @ Jun 26 2009, 11:33) *
Не помогло.

Теперь же:
Цитата(n_bogoyavlensky @ Jun 29 2009, 10:08) *
Только вот указатель realloc() я передаю ненулевой... может в этом ещё дело...


Не понятно, кроме того что не смешно cranky.gif
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th June 2025 - 06:49
Рейтинг@Mail.ru


Страница сгенерированна за 0.01502 секунд с 7
ELECTRONIX ©2004-2016