Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Почему функция sscanf требует около 50кБ памяти?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
aabmail
Здравствуйте, уважаемые форумчане!

Возникла проблема с linking gcc в среде Xilinx SDK (Eclipse).

Почему из-за функции sscanf сегмент .text увеличивается в размере на 50 кБайт (а может и больше)? Не потому ли, что вместе с sscanf в .text попадает целиком вся библиотека ввода/вывода.
Как сделать так, чтобы прилинковывалась не вся библиотека, а только те функции, которые вывываются из программы.

Или я что-то в корне не понимаю. Заранее благодарен за любые комментарии.
Сергей Борщ
Цитата(aabmail @ Mar 20 2014, 10:26) *
Или я что-то в корне не понимаю.
Создайте .map (ключ для gcc -Wl.-Map=имя_файла). Рассмотрите его внимательно. В для каждой притянутой из библиотеки функции написано, какая функция ее вызвала. Не знаю про Xilinx, но обычно gcc-реализация (s)scanf тянет за собой менеджер памяти и кучу прочих вещей. Как раз где-то на 50К.
DASM
Да она и сама по себе в полном виде на почти столько и тянет sm.gif
scifi
Кстати, как-то раз взял из тырнета чей-то sprintf() - получилось около 4К байт кода и никаких malloc(). С тех пор повсеместно использую. Есть ли что-то подобное для sscanf? Поиск в гугле навскидку результата не дал.
megajohn
Цитата(scifi @ Mar 21 2014, 07:18) *
Кстати, как-то раз взял из тырнета чей-то sprintf() - получилось около 4К байт кода и никаких malloc()


да я вообще полагал, что sprintf sscanf должны работать только на стеке. И вроде так и есть в IAR. Или нет ?
Сергей Борщ
Цитата(megajohn @ Mar 21 2014, 05:24) *
И вроде так и есть в IAR. Или нет ?
В ИАРе может и так. А в комплекте gcc в качестве стандартной библиотеки идет newlib, которая изначально заточена под большие компы, многопоточность и буферизованный вывод. Только недавно в нех появилась возможность собирать "нано"-версию. Возможно это чем-то поможет автору ветки. Я код newlib внимательно не изучал, видел лишь имена функций, которые подтягивает sscanf и ssprintf. Вроде как printf использует динамическую память при первом вызове для создания структур потокового ввода-вывода и их буферов.
aabmail
Цитата(Сергей Борщ @ Mar 20 2014, 13:33) *
Создайте .map (ключ для gcc -Wl.-Map=имя_файла). Рассмотрите его внимательно. В для каждой притянутой из библиотеки функции написано, какая функция ее вызвала. Не знаю про Xilinx, но обычно gcc-реализация (s)scanf тянет за собой менеджер памяти и кучу прочих вещей. Как раз где-то на 50К.


Я сгенерировал map-файл, но сильно закапываться в него не стал. Как я понял, в .text попадает целиком не вся библиотека ввода/вывода, а только нужные функции. Верно?

Цитата(scifi @ Mar 21 2014, 06:18) *
Кстати, как-то раз взял из тырнета чей-то sprintf() - получилось около 4К байт кода и никаких malloc(). С тех пор повсеместно использую. Есть ли что-то подобное для sscanf? Поиск в гугле навскидку результата не дал.


Для microBlaze специально сделан так называемый xil_printf, который не поддерживает плавающую точку. Он отъедает около 3-х килобайт.
Однако для sscanf такой халявы нет.

Мне в общем-то не нужен парсинг строк с вещественными числами с фиксированной точкой, а также с тестовыми подстроками.
Нет ли у кого? Не хотелось бы самому это писать.

Цитата(megajohn @ Mar 21 2014, 06:24) *
да я вообще полагал, что sprintf sscanf должны работать только на стеке. И вроде так и есть в IAR. Или нет ?


В GNU GCC не на стеке.

Цитата(Сергей Борщ @ Mar 21 2014, 06:55) *
В ИАРе может и так. А в комплекте gcc в качестве стандартной библиотеки идет newlib, которая изначально заточена под большие компы, многопоточность и буферизованный вывод. Только недавно в нех появилась возможность собирать "нано"-версию. Возможно это чем-то поможет автору ветки. Я код newlib внимательно не изучал, видел лишь имена функций, которые подтягивает sscanf и ssprintf. Вроде как printf использует динамическую память при первом вызове для создания структур потокового ввода-вывода и их буферов.


В Xilinx SDK newlib, к сожалению, не поставляется.

Всем большое спасибо за ответы.
Сергей Борщ
Цитата(aabmail @ Mar 21 2014, 09:25) *
Я сгенерировал map-файл, но сильно закапываться в него не стал.
там самыми первыми строками должно идти что-то вроде
Код
Archive member included because of file (symbol)

/opt/arm-gcc/linaro/20130313/bin/../lib/gcc/arm-none-eabi/4.7.3/armv7-m/libgcc.a(_arm_addsubdf3.o)
                              ./release/obj/floatp10.o (__aeabi_dadd)
/opt/arm-gcc/linaro/20130313/bin/../lib/gcc/arm-none-eabi/4.7.3/armv7-m/libgcc.a(_arm_muldivdf3.o)
                              ./release/obj/floatp10.o (__aeabi_dmul)
/opt/arm-gcc/linaro/20130313/bin/../lib/gcc/arm-none-eabi/4.7.3/armv7-m/libgcc.a(_arm_cmpdf2.o)
                              ./release/obj/floatp10.o (__aeabi_dcmpeq)

Цитата(aabmail @ Mar 21 2014, 09:25) *
Как я понял, в .text попадает целиком не вся библиотека ввода/вывода, а только нужные функции. Верно?
Для библиотеки - да. Из нее тянется только то, что нужно. Кому нужно - см. начало .map.
Из исходников по умолчанию линкуется все. Чтобы этого не происходило, надо компилировать с ключами -ffunction-sections, -fdata-sections и линковать с ключем -Wl,--gc-sections. Тогда компилятор поместит каждую функцию и каждую переменную в свою секцию, а линкер выкинет те секции, на которые нет ссылок. Без этого все функции попадают в один глобальный сегмент .text, а данные - в .data и .bss. С этими ключами - функции попадают в .text.<имя_функции>, данные - аналогично и линкер может легко отделить мух от котлет.
aabmail
Цитата(Сергей Борщ @ Mar 21 2014, 11:07) *
там самыми первыми строками должно идти что-то вроде


У меня аналогично:
Код
Archive member included because of file (symbol)

../../standalone_bsp_1/microblaze_1/lib\libxil.a(xil_printf.o)
                              ./src/helloworld.o (xil_printf)
../../standalone_bsp_1/microblaze_1/lib\libxil.a(_exception_handler.o)
                              c:/xilinx/14.7/ise_ds/edk/gnu/microblaze/nt/bin/../lib/gcc/microblaze-xilinx-elf/4.6.4/../../../../microblaze-xilinx-elf/lib/m/mh/le/crt0.o (_exception_handler)
../../standalone_bsp_1/microblaze_1/lib\libxil.a(_program_clean.o)
                              c:/xilinx/14.7/ise_ds/edk/gnu/microblaze/nt/bin/../lib/gcc/microblaze-xilinx-elf/4.6.4/../../../../microblaze-xilinx-elf/lib/m/mh/le/crtinit.o (_program_clean)



Цитата(Сергей Борщ @ Mar 21 2014, 11:07) *
надо компилировать с ключами -ffunction-sections, -fdata-sections и линковать с ключем -Wl,--gc-sections. Тогда компилятор поместит каждую функцию и каждую переменную в свою секцию, а линкер выкинет те секции, на которые нет ссылок. Без этого все функции попадают в один глобальный сегмент .text, а данные - в .data и .bss. С этими ключами - функции попадают в .text.<имя_функции>, данные - аналогично и линкер может легко отделить мух от котлет.


Похоже, этих премудростей мой GCC не знает...
Код
make all
'Building file: ../src/helloworld.c'
'Invoking: MicroBlaze gcc compiler'
mb-gcc -Wall -O0 -g3 -c -fmessage-length=0 -Wno-implicit-function-declaration  -fno-builtin-strlen -fno-builtin-memcpy -ffunction-sections, -fdata-sections -I../../standalone_bsp_1/microblaze_1/include -mlittle-endian -mxl-pattern-compare -mno-xl-soft-div -mcpu=v8.50.c -mno-xl-soft-mul -mxl-multiply-high -mhard-float -mxl-float-convert -mxl-float-sqrt -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"src/helloworld.d" -MT"src/helloworld.d" -o "src/helloworld.o" "../src/helloworld.c"
cc1.exe: error: unrecognized command line option '-ffunction-sections,'
make: *** [src/helloworld.o] Ошибка 1


-------------
SORRY.

Не работало из-за лишней запятой в командной строке. С этими опциями все собирается, правда эффекта никакого. Видимо, из программы нечего выкидывать.
Спасибо.
scifi
Цитата(aabmail @ Mar 21 2014, 13:56) *
С этими опциями все собирается, правда эффекта никакого. Видимо, из программы нечего выкидывать.

А вы не забыли об опциях линкера -Wl,--gc-sections ?
aabmail
Цитата(scifi @ Mar 21 2014, 13:42) *
А вы не забыли об опциях линкера -Wl,--gc-sections ?


Точно не забыл. Программа маленькая, еще не успел лишнего понаписать sm.gif . А вот sscanf 50% памяти сожрал.

Кроме этого на http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gc...ze-Options.html
написано: Only use these options when there are significant benefits from doing so. When you specify these options, the assembler and linker will create larger object and executable files and will also be slower.
Поэтому решил эти опции не указывать.
scifi
Я и раньше натыкался на Nuttx. Там в комплекте идёт своя стандартная библиотека. Вроде бы sscanf выглядит вменяемо.
Krys
Цитата(Сергей Борщ @ Mar 20 2014, 16:33) *
Создайте .map (ключ для gcc -Wl.-Map=имя_файла).
Подскажите, пожалуйста, новичку, куда это вписывать? Я попробовал сюда:

Нажмите для просмотра прикрепленного файла

Не помогло, после сборки не нашёл такого файла.
Сергей Борщ
Я не использую этот плугин, поэтому конкретное место не подскажу. Но видите на вашей картинке чуть ниже обведенного есть поле All options. Вот вам надо добиться, чтобы оно появилось в этом поле. Поищите в подразделах General, Mascellaneous или в других. Возможно вы найдете галочку вроде "генерить .map-файл" и она добавит эту опцию сама.
Krys
Там галочки можно поставить только в General:

Нажмите для просмотра прикрепленного файла

В остальных разделах нет галочек, только вводить можно текстовые поля.

Короче я в консоли смотрю результат запуска линкера, вот так печатает:
Код
'Invoking: MicroBlaze gcc linker'
mb-gcc -Wl.-Map=../src/test_paul.map -L../../fft_sp605_bsp/microblaze_0/lib -Wl,-T -Wl,../src/lscript.ld -L../../fft_sp605_bsp/microblaze_0/lib -mlittle-endian -mxl-barrel-shift -mxl-pattern-compare -mcpu=v8.50.c -mno-xl-soft-mul -Wl,--no-relax -Wl,--gc-sections -o "fft_sp605.elf"  ./src/main.o ./src/platform.o   -Wl,--start-group,-lxil,-lgcc,-lc,--end-group


Т.е. в принципе эта опция туда пролазит по синтаксису нормально, и он на синтаксис вызова не ругается. Другое дело, что и файла не создаёт )))
Либо ещё как вариант: может он файл создаёт, а потом стирает как ненужный мусор?
Путь к файлу пробовал указывать вообще без пути, пробвал по аналогии с остальными путями ставить не ../src, а ./src - результат тот же...

Добавление:
Решилась проблема, надо было запятую поставить, а не точку )))
doom13
Цитата(Сергей Борщ @ Mar 21 2014, 11:07) *
Из исходников по умолчанию линкуется все. Чтобы этого не происходило, надо компилировать с ключами -ffunction-sections, -fdata-sections и линковать с ключем -Wl,--gc-sections. Тогда компилятор поместит каждую функцию и каждую переменную в свою секцию, а линкер выкинет те секции, на которые нет ссылок. Без этого все функции попадают в один глобальный сегмент .text, а данные - в .data и .bss. С этими ключами - функции попадают в .text.<имя_функции>, данные - аналогично и линкер может легко отделить мух от котлет.

Приветствую.
Делаю проект в Xilinx SDK для MicroBlaze. Написал прстенький драйвер на базе класса c++, создаю объект, вызаваю пару функций. После компиляции выдаёт ошибку, что нехватает ещё 190 кБ памяти. Наткнулся на данную тему и вышеописанные ключи очень даже помогли. С ними размер кода уменьшился до 62 кБ, но если отказаться от использования классов и использовать только функции в стиле си, то размер программы (код примерно одинаков в обоих случаях) ужимается до 30 кБ. Возможно ли задать компилятору ещё какие-то дополнительные опции для уменьшения размера прошивки?
Спасибо.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.