GenaSPB 11 9 марта, 2020 Опубликовано 9 марта, 2020 (изменено) · Жалоба Quote Memory for variable length arrays is allocated at runtime, on the heap Какая такая куча? Процитированное немного бред. На стеке да... Изменено 9 марта, 2020 пользователем GenaSPB Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Grizzly 0 9 марта, 2020 Опубликовано 9 марта, 2020 · Жалоба 12 минут назад, GenaSPB сказал: Какая такая куча? Действительно, на куче... Здесь аналогичное пишут. Странно. Тогда ведь и malloc можно применить вместо VLA. http://www.keil.com/support/man/docs/armcc/armcc_chr1359124223721.htm Насколько я понимаю, стандартом не указано, где располагать такие массивы. В GCC действительно на стеке. Такой выбор как раз понятен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 9 марта, 2020 Опубликовано 9 марта, 2020 · Жалоба А действительно: как компилятору адресовать локальные переменные функции на стеке и аргументы функции в случае, если на стеке будет создан массив переменного размера? Ведь при выделении стека для него, регистр SP должен быть сдвинут вниз на переменную величину (определяемую в runtime), а значит адресовывать их через константное смещение относительно SP - уже не получится. А значит видимо в такой функции компилятору нужно будет сохранить начальное состояние SP (на входе в функцию) в дополнительном регистре (зарезервировать дополнительный регистр (указатель) для этого) и адресовывать аргументы функции до неё через этот регистр (и сам массив). А если таких массивов два? Тогда нужно уже два таких регистра-указателя. И т.д. В то время как с массивами константного размера можно их все (хоть сколько их штук) адресовать через SP. Это ещё один минус массивов переменной длины - необходимость лишних указателей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 45 9 марта, 2020 Опубликовано 9 марта, 2020 · Жалоба 4 часа назад, Darth Vader сказал: Вот ещё нашлось. Вцелом, повторяет информацию с сайта ARM. Но добавлено ещё примечание, что память под такие массивы выделяется в куче. Ну так всё-таки, где им выделяется место? На стеке (stack) или в куче (heap)? А то здесь все согласно кивают головами, делая вид, что стек и куча - одно и то же. Тогда как автоматические переменные хранятся на стеке, а если в хипе, то это уже динамически аллокируемая переменная/массив. Неужели до сих пор никто так и не заглянул в код компиляции, чтобы узнать, какую память отводит компилятор под VLA-массивы? Так и будем на ромашке гадать, на разные ссылочки друг другу пальчиком показывая? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
V_G 11 9 марта, 2020 Опубликовано 9 марта, 2020 · Жалоба 1 час назад, Xenia сказал: Ну так всё-таки, где им выделяется место? На стеке (stack) или в куче (heap)? Я вот не понял, почему обсуждение проблемы динамических массивов свелось к обсуждению места (непонятного), которое им выделяют разные компиляторы? Почему нельзя самому жестко зафиксировать за собой место с помощью malloc (и далее new,realloc,delete,free) или других функций динамического выделения памяти? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 222 10 марта, 2020 Опубликовано 10 марта, 2020 · Жалоба 7 часов назад, Xenia сказал: Ну так всё-таки, где им выделяется место? Как и другие локальные переменные - в стеке. В этом легко убедиться заглянув в ассемблерный листинг преамбулы функции. Для выделения в куче служат другие средства библиотеки/языка. 5 часов назад, V_G сказал: Я вот не понял, почему обсуждение проблемы динамических массивов свелось к обсуждению места (непонятного), которое им выделяют разные компиляторы? По-моему проблема вообще не стоит обсуждения, т.к. найти ответы на все вопросы можно за 5 минут поиска в Гугле и чтения Wiki/описаний конкретного компилятора. Ссылки даны выше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 10 марта, 2020 Опубликовано 10 марта, 2020 · Жалоба 9 часов назад, Xenia сказал: Неужели до сих пор никто так и не заглянул в код компиляции, чтобы узнать, какую память отводит компилятор под VLA-массивы? Видимо те, кто их использует (VLA), никогда не заглядывают в листинги.Не умеют просто. А те кто заглядывает, и задумывается о качестве результирующего кода, те не используют VLA. Недавно был тред о необходимости "заглядывания в листинги". Очень показательный. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 26 10 марта, 2020 Опубликовано 10 марта, 2020 · Жалоба 30 minutes ago, jcxz said: А те кто заглядывает, и задумывается о качестве результирующего кода, те не используют VLA. Только здравый смысл и пониманием работы компилятора запрещает использовать этот VLA там, где ему не место. Глядеть для этого в листинги вовсе необязательно ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 141 10 марта, 2020 Опубликовано 10 марта, 2020 · Жалоба 2 часа назад, makc сказал: Как и другие локальные переменные - в стеке. Вы забыли дописать "обычно". Потому что в справке на конкретный обсуждаемый компилятор (на которую выше давались ссылки) явно сказано, что именно он выделяет в куче. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 222 10 марта, 2020 Опубликовано 10 марта, 2020 · Жалоба 9 минут назад, Сергей Борщ сказал: Вы забыли дописать "обычно". Потому что в справке на конкретный обсуждаемый компилятор (на которую выше давались ссылки) явно сказано, что именно он выделяет в куче. Согласен, но пока я не видел ни одного примера описанного поведения. Хотя, естественно, это мало о чем говорит, т.к. в стандарте C нет понятия "стек" и поэтому апеллировать к стандарту не получится, что открывает возможность разработчикам сделать это по-своему. Но с другой стороны управление кучей отдано на откуп системной библиотеке и по факту является специфичным для проекта, т.к. мы для себя используем свой malloc (да и реализаций этого malloc есть довольно много разных и они по определению несовместимы): Цитата 7.20.3 Memory management functions The order and contiguity of storage allocated by successive calls to the calloc, malloc, and realloc functions is unspecified. The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly freed or reallocated). Each such allocation shall yield a pointer to an object disjoint from any other object. Кроме того такое размещение VLA в куче дает лишние бинарные зависимости. Таким образом получается, что использование массивов переменной длины, размещаемых в куче, может очень интересным образом сломать проект, подтянув дополнительный malloc из библиотеки компилятора в дополнение к уже используемому собственному malloc'у. PS: Я склонен считать, что в упомянутой выше документации техническая ошибка. Попробую это проверить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 45 10 марта, 2020 Опубликовано 10 марта, 2020 · Жалоба 13 часов назад, V_G сказал: Я вот не понял, почему обсуждение проблемы динамических массивов свелось к обсуждению места (непонятного), которое им выделяют разные компиляторы? Почему нельзя самому жестко зафиксировать за собой место с помощью malloc (и далее new,realloc,delete,free) или других функций динамического выделения памяти? Потому что динамически из хипа аллокировать массивы вы всегда могли (это параметр у malloc), и для этого никакой VLA не нужен. Тогда как VLA может быть интересен только в том случае, если он способен выделять место массиву на стеке. Отсюда и вопросы про VLA - откуда он выделяет память под массивы? Если динамически из хипа, то нафиг он тогда нужен, а если из стека, то тогда это полезный инструмент. Скажем, если некая функция, вызывается миллион раз в секунду, всякий раз при входе аллокируя память из хипа, а при выходе ее деаллокируя, то будет большой объем лишних операций, обременительных для МК с небольшими тактовыми частотами. Кроме того, я не знаю (да и знать не хочу), реентерабелен malloc или нет, т.е. могу ли я такую функцию из прерывания вызывать в то время, когда какая-то другая функция что-то себе из хипа выуживает. Тогда как выделение и освобождение памяти на стеке происходит практически мгновенно и не вызывает коллизий при использовании в процедурах прерывания. 7 часов назад, makc сказал: Как и другие локальные переменные - в стеке. В этом легко убедиться заглянув в ассемблерный листинг преамбулы функции. Для выделения в куче служат другие средства библиотеки/языка. Именно ради этого я и просила в тот ассемблерный листинг заглянуть. И свой комментарий по поводу сообщения Darth Vader'а написала потому, что в ссылке, которую он дал, было написано: "Memory for variable length arrays is allocated at runtime, on the heap." (ARM Keil). После этого бодания на тему, чья ссылка лучше, перестали иметь смысл, и оставалось только одно - проверить, как поступает в этих случаях каждый конкретный компилятор. Ваш ответ я тоже не могу принять, поскольку вы умолчали о том, каким компилятором пользовались. Вдруг у вас Keil? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 222 10 марта, 2020 Опубликовано 10 марта, 2020 · Жалоба Admin: оффтопик на тему русского языка скрыт. Придерживайтесь темы и соблюдайте Правила. По теме. 2 часа назад, Xenia сказал: Вдруг у вас Keil? Нет, у меня gcc разных версий и мне его хватает на все 100%. Попробовал скомпилировать простой исходник в ARM Compiler 6.5: Спойлер #include <string.h> int f(int n) { int a[n]; memset(a, 0, sizeof(a)); return a[0] + a[1]; } И вот что получилось: Спойлер f: .fnstart @ BB#0: .save {r4, r6, r7, lr} push {r4, r6, r7, lr} .setfp r7, sp, #8 add r7, sp, #8 .pad #24 sub sp, #24 mov r1, r0 str r0, [r7, #-12] mov r2, sp str r2, [r7, #-16] movs r2, #7 add.w r2, r2, r0, lsl #2 bic r2, r2, #7 mov r3, sp subs r2, r3, r2 mov sp, r2 lsls r0, r0, #2 str r0, [r7, #-20] @ 4-byte Spill mov r0, r2 ldr r3, [r7, #-20] @ 4-byte Reload str r1, [r7, #-24] @ 4-byte Spill mov r1, r3 str r2, [r7, #-28] @ 4-byte Spill bl __aeabi_memclr4 ldr r0, [r7, #-28] @ 4-byte Reload ldr r1, [r0] ldr r2, [r0, #4] adds r0, r1, r2 ldr r1, [r7, #-16] mov sp, r1 sub.w r4, r7, #8 mov sp, r4 pop {r4, r6, r7, pc} Самое интересное кроется в строках: movs r2, #7 add.w r2, r2, r0, lsl #2 bic r2, r2, #7 mov r3, sp subs r2, r3, r2 mov sp, r2 Как вы можете заметить, здесь не используется выделение в куче, используется стек. При этом в стеке выделяется необходимое количество памяти и далее изменяется значение указателя стека (sp). Так что не только gcc выделяет локальные переменные в стеке, включая и массивы переменной длины. На сколько я понимаю, в Keil MDK используется тот же компилятор ARM Compiler 6.5 и поэтому он так же должен выделять VLA в стеке. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Grizzly 0 10 марта, 2020 Опубликовано 10 марта, 2020 · Жалоба 35 минут назад, makc сказал: Keil MDK используется тот же компилятор ARM Compiler 6.5 Нет, не так. 6.y основан на clang, это armclang, а 4.y, 5.y - это armcc, что-то из разработок Keil. Поведение 6.5 с выделением на стеке, таким образом, полностью ожидаемо. Надо ждать листинга версии 5.y. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 222 10 марта, 2020 Опубликовано 10 марта, 2020 · Жалоба Ок, возражение принимается. Попробовал в armcc 5.06: Спойлер ; generated by Component: ARM Compiler 5.06 update 3 (build 300) Tool: armcc [4d35f0] ; commandline armcc [--thumb -c -S --vla test.c] THUMB REQUIRE8 PRESERVE8 AREA ||.text||, CODE, READONLY, ALIGN=1 f PROC PUSH {r4-r6,lr} LSLS r0,r0,#2 MOVS r5,r0 BL malloc MOVS r4,r0 MOVS r1,r5 BL __aeabi_memclr4 LDM r4!,{r0,r1} ADDS r5,r0,r1 MOVS r0,r4 SUBS r0,r0,#8 BL free MOVS r0,r5 POP {r4-r6,pc} ENDP AREA ||.arm_vfe_header||, DATA, READONLY, NOALLOC, ALIGN=2 DCD 0x00000000 EXPORT f [CODE] IMPORT ||Lib$$Request$$armlib|| [CODE,WEAK] IMPORT malloc [CODE] IMPORT __aeabi_memclr4 [CODE] IMPORT free [CODE И тут действительно вызывается malloc/free. Ужасно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Grizzly 0 10 марта, 2020 Опубликовано 10 марта, 2020 · Жалоба 2 часа назад, makc сказал: И тут действительно вызывается malloc/free. Спасибо большое! А то уже давно нет под рукой этих тулчейнов. Ужасно P.S. Мне как-то давно говорили, что armcc основан на каком-то древнем GCC, потом у GCC сменилась лицензия, все стало совсем жёстко, в Keil продолжили пилить сами. Видимо, это как раз их собственная реализация VLA. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться