Важная информация

User Tag List

Показано с 1 по 10 из 10

Тема: Работа malloc/free в SDCC/Z80

  1. #1
    Veteran Аватар для Oleg N. Cher
    Регистрация
    24.08.2007
    Адрес
    Днепропетровская обл.
    Сообщений
    1,593
    Спасибо Благодарностей отдано 
    2,158
    Спасибо Благодарностей получено 
    130
    Поблагодарили
    96 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию Работа malloc/free в SDCC/Z80

    Всем привет.

    Столкнулся с проблемой странной работы malloc. При зарезервированном под кучу килобайте и запросе памяти под структуру размером 25 байт память выделяется первых 2 вызова, потом malloc начинает всегда возвращать 0.

    Пример кода, воспроизводящего ошибку

    Требуется консультация опытных товарищей. Замечу, что:

    a) пробовались разные сборки SDCC, в т.ч. и старые, и свежие;
    b) для задания размера кучи мануал советует перекомпилировать _heap.c с новым размером:

    sdcc -c _heap.c -DHEAP_SIZE=2048

    но если добавить ключик -mz80, SDCC сразу начинает ругаться на конструкцию __xdata. И хотя её можно закомментировать, я не уверен, что это хорошая идея.

    1. Чего там с malloc не так?
    2. Как задавать размер кучи в случае с Z80 (который явно не предусмотрен?)?

    Вот такие вопросы.

    К оф.разрабам пока не обращался, может сами разрулим. Т.к. есть подозрение, что может это и не баг. Филипп отбрил, сказал, нет времени.
    Последний раз редактировалось Oleg N. Cher; 16.07.2013 в 13:14.

  2. #1
    С любовью к вам, Yandex.Direct
    Размещение рекламы на форуме способствует его дальнейшему развитию

  3. #2
    Activist
    Регистрация
    21.12.2005
    Адрес
    Kyiv/Ukraine
    Сообщений
    415
    Спасибо Благодарностей отдано 
    7
    Спасибо Благодарностей получено 
    1
    Поблагодарили
    1 сообщение
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Я вообще malloc/free нигде не юзаю, при компиляции под z80.
    Т.к. он может фрагментировать память.


    Для задания размера кучи, пробуй так:
    Создай асм файл myheap.s, с таким содержимым (вместо 0, проставишь размер кучи)
    .area _HEAP
    .ds 0

    И включи этот файл в компиляцию своей программы.
    Потом в .map файле проверь, что l__HEAP равен, значению заданному тобой в myheap.s
    Последний раз редактировалось Valen; 16.07.2013 в 20:14.
    V6Z80P - Back for Good

  4. #3
    Veteran
    Регистрация
    08.05.2007
    Адрес
    Dnepropetrovsk
    Сообщений
    1,053
    Спасибо Благодарностей отдано 
    218
    Спасибо Благодарностей получено 
    47
    Поблагодарили
    31 сообщений
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Конкретно с проблемой данного компилятора не сталкивался и не разбирался, но выскажу общее соображение. При организации кучи ведь имеются накладные расходы по памяти. Что если они так велики, что исчерпывают все 1024 байта после выделения двух блоков по 25 байт?

  5. #4
    Veteran Аватар для Oleg N. Cher
    Регистрация
    24.08.2007
    Адрес
    Днепропетровская обл.
    Сообщений
    1,593
    Спасибо Благодарностей отдано 
    2,158
    Спасибо Благодарностей получено 
    130
    Поблагодарили
    96 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Barmaley_m, если это так, то нужно дорабатывать алгоритм выделения памяти. Не верю, что нельзя сделать экономичнее. Даже старый добрый Hisoft Pascal не разбазаривал динамическую память такими темпами.

    Что касаемо самой необходимости malloc на Z80 - да, для большинства применений это слишком громоздко и неэффективно, хватит и статического распределения. Но для некоторых задач динамика сгодится, например, для быстрого макетирования алгоритмов на Обероне/Си, чтобы потом для эффективности переписать на ассемблер.

  6. #5
    Activist
    Регистрация
    21.12.2005
    Адрес
    Kyiv/Ukraine
    Сообщений
    415
    Спасибо Благодарностей отдано 
    7
    Спасибо Благодарностей получено 
    1
    Поблагодарили
    1 сообщение
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Да, не выдумывайте,
    там оверхед, всего несколько байт на выделяемый блок памяти.
    См. _malloc.c

    Можно, конечно malloc юзать.
    Работать он должен, если правильно размер кучи установлен, для программы.
    Более того, если только один раз вызвать malloc() для всех нужных объектов и не вызывать free,
    то даже и фрагментации не будет.
    Последний раз редактировалось Valen; 17.07.2013 в 20:21.
    V6Z80P - Back for Good

  7. #6
    Veteran Аватар для Oleg N. Cher
    Регистрация
    24.08.2007
    Адрес
    Днепропетровская обл.
    Сообщений
    1,593
    Спасибо Благодарностей отдано 
    2,158
    Спасибо Благодарностей получено 
    130
    Поблагодарили
    96 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Сделал как посоветовал Valen. Размер кучи установил в 4 кб. Результат тот же. Вот .map файл для деталей, и, кажется, тут не всё в порядке:
    Код:
    Area                                    Addr        Size        Decimal Bytes (Attributes)
    --------------------------------        ----        ----        ------- ----- ------------
    _HEAP                               0000C35D    000013FF =        5119. bytes (REL,CON)
    
          Value  Global                              Global Defined In Module
          -----  --------------------------------   ------------------------
         0000D35D  __sdcc_heap_start                  
    
    ASxxxx Linker V03.00 + NoICE + sdld,  page 6.
    Hexadecimal  [32-Bits]
    
    Area                                    Addr        Size        Decimal Bytes (Attributes)
    --------------------------------        ----        ----        ------- ----- ------------
    _HEAP_END                           0000D75C    00000001 =           1. bytes (REL,CON)
    
          Value  Global                              Global Defined In Module
          -----  --------------------------------   ------------------------
         0000D75C  __sdcc_heap_end
    Здесь не понимаю откуда берётся число 5119 (13FF), ведь в асм-файле задан размер 4096 байт.

    Теперь если не задавать при компиляции myheap.rel, то размер кучи становится 1 кб:
    Код:
    Area                                    Addr        Size        Decimal Bytes (Attributes)
    --------------------------------        ----        ----        ------- ----- ------------
    _HEAP                               0000C35D    000003FF =        1023. bytes (REL,CON)
    
          Value  Global                              Global Defined In Module
          -----  --------------------------------   ------------------------
         0000C35D  __sdcc_heap_start                  
    
    ASxxxx Linker V03.00 + NoICE + sdld,  page 6.
    Hexadecimal  [32-Bits]
    
    Area                                    Addr        Size        Decimal Bytes (Attributes)
    --------------------------------        ----        ----        ------- ----- ------------
    _HEAP_END                           0000C75C    00000001 =           1. bytes (REL,CON)
    
          Value  Global                              Global Defined In Module
          -----  --------------------------------   ------------------------
         0000C75C  __sdcc_heap_end
    Т.е. установка размера кучи таки работает! Но malloc по-прежнему не отрабатывает. Если не трудно, прошу, Valen, прогоните пример кода, приведённого выше, у себя при разных размерах кучи и желательно свежим билдом SDCC, если это как-то заработает у Вас - будем искать чего я делаю не так.

  8. #7
    Veteran Аватар для Oleg N. Cher
    Регистрация
    24.08.2007
    Адрес
    Днепропетровская обл.
    Сообщений
    1,593
    Спасибо Благодарностей отдано 
    2,158
    Спасибо Благодарностей получено 
    130
    Поблагодарили
    96 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Вопросы решились, всем спасибо.

    Цитата Сообщение от Maarten Brock
    You should use heap.s instead of _heap.c for the z80.
    You should also call _sdcc_heap_init() for the z80.

  9. #8
    Activist
    Регистрация
    21.12.2005
    Адрес
    Kyiv/Ukraine
    Сообщений
    415
    Спасибо Благодарностей отдано 
    7
    Спасибо Благодарностей получено 
    1
    Поблагодарили
    1 сообщение
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от Oleg N. Cher Посмотреть сообщение
    You should use heap.s instead of _heap.c for the z80.
    Да, вот в файле heap.s и стоит выделение 1KB кучи.

    Т.е. для задания размера кучи есть два пути
    - перекомпилить heap.s и затем пере-компилить либу z80.lib
    - включить в компиляцию своей программы, свой асм файл с выделением места в heap, как я описывал выше


    Если там ты выделял, в myheap.s 4KB, то суммарный размер кучи будет 1 + 4 = 5KB
    Вот такая математика.


    Цитата Сообщение от Oleg N. Cher Посмотреть сообщение
    You should also call _sdcc_heap_init() for the z80.
    Вот про это вообще не знал.
    V6Z80P - Back for Good

  10. #9
    Veteran Аватар для Oleg N. Cher
    Регистрация
    24.08.2007
    Адрес
    Днепропетровская обл.
    Сообщений
    1,593
    Спасибо Благодарностей отдано 
    2,158
    Спасибо Благодарностей получено 
    130
    Поблагодарили
    96 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Да, хитро, однако же. Но алгоритм выделения памяти совсем неплохо работает. И разница между статическим и динамическим выделением в размере кода - всего какой-то килобайт.

    А ещё я не нашёл в каком *.h-файле описан прототип функции _sdcc_heap_init()
    Поэтому описал его сам:

    Код:
    void _sdcc_heap_init (void);
    #ifndef SYSTEM_Cfg_Use_HEAP
    #  define Platform__init()
    #else
    #  define Platform__init() _sdcc_heap_init()
    #endif

  11. #10
    Activist
    Регистрация
    21.12.2005
    Адрес
    Kyiv/Ukraine
    Сообщений
    415
    Спасибо Благодарностей отдано 
    7
    Спасибо Благодарностей получено 
    1
    Поблагодарили
    1 сообщение
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Напоминаю как можно установить свой размер для кучи в sdcc.
    (если не устраивает размер по умолчанию 1 KB)

    - скопировать файл heap.s себе в папку проекта
    - в файле heap.s прописать свой желаемый размер кучи
    - скомпилить и слинковать этот файл со своей программой
    - не забыть вызвать _sdcc_heap_init(), для инициализации кучи

    Как проверить, что размер кучи поменялся.
    1. проверить в map файле, что размер сегмента _HEAP именно тот, который вы установили в файле heap.s
    2. выполнить такой код и проверить что результат тот же, что и в п.2
    Код:
    extern char _sdcc_heap_start;
    extern char _sdcc_heap_end;
    ...
    unsigned int heap_size = &_sdcc_heap_end - &_sdcc_heap_start;


    -----------------------
    Оригинальный ответ:

    The answer is that, on Z80 systems, heap size is hard-coded to 1kB.
    Maarten Brock answered this on the sdcc-user mailing list.

    You have to create the heap yourself if the standard 1kB is not enough.
    Copy heap.s into your project dir and modify it to create your preferred size. Then assemble it and link with your project.

    Unlike the mcs51 heap which is defined in _heap.c this is not documented for Z80 in the manual.
    Feel free to request a documentation update or merge of _heap.c and heap.s in the tracker system.
    V6Z80P - Back for Good

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. sdcc. с чего начать.
    от ALKO в разделе Программирование
    Ответов: 42
    Последнее: 16.09.2012, 15:49
  2. Ответов: 0
    Последнее: 15.12.2009, 09:39
  3. SDCC вокруг да около
    от andrews в разделе Программирование
    Ответов: 8
    Последнее: 26.03.2008, 08:16
  4. New Free Spectrum Game
    от Jonathan в разделе RST#38
    Ответов: 4
    Последнее: 21.06.2007, 21:33

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •