LINUX.ORG.RU

переменная в Си


0

0

Нужно в программе на Си создать массив 16Кб. Скажите, лучше это сделать в области данных или в стэке? Какие плюсы минусы?

anonymous

А где он создаётся ? Можно и так и так, 16 Кб - не 16 Мб.

Krasu
()

IMHO в стэке не должно быть ничего длиннее нескольких сот байт. Иначе при рекурсии ты быстренько отожрешь под стэк всю память.

Die-Hard ★★★★★
()

>Скажите, лучше это сделать в области данных или в стэке?

В области данных (про bss речь?) можно выделить только фиксированную область.

Если нужны динамические структуры (нефиксированного размера), которые можно освобождать, то тут стоит использовать или стек или malloc.

У стека (локальные переменные и alloca) тот плюс, что не надо внимательно следить за освобождением памяти. С другой стороны, поскольку такая память освобождается автоматически, нужно быть осторожным с передачей указателей на эту память. Ну и про рекурсию верно сказано.

Murr ★★
()
Ответ на: комментарий от anonymous

>А если 16Мб? В чем минус?

Вопрос очень расплывчатый, чтобы на него можно было четко ответить.

Если нюансов с передачей указателей нет и массив выделяется один, то по большому счету разницы нет.

Murr ★★
()
Ответ на: комментарий от anonymous

[root@murmillo tmp]# ulimit -s
10240
[root@murmillo tmp]# cat ttt.c
int main(int argc, char *argv[]) {
    char local[16*1048576];

    local[0] = 1;

    return 0;
}
[root@murmillo tmp]# gcc ttt.c -g
[root@murmillo tmp]# objdump -S --prefix-addresses -M intel

a.out:     формат файла elf32-i386

Диассемблирование раздела .init:
int main(int argc, char *argv[]) {
08048334 <main> push   ebp
08048335 <main+0x1> mov    ebp,esp
08048337 <main+0x3> sub    esp,0x1000008
0804833d <main+0x9> and    esp,0xfffffff0
08048340 <main+0xc> mov    eax,0x0
08048345 <main+0x11> add    eax,0xf
08048348 <main+0x14> add    eax,0xf
0804834b <main+0x17> shr    eax,0x4
0804834e <main+0x1a> shl    eax,0x4
08048351 <main+0x1d> sub    esp,eax
    char local[16*1048576];

    local[0] = 1;
08048353 <main+0x1f> mov    BYTE PTR [ebp-16777224],0x1

    return 0;
0804835a <main+0x26> mov    eax,0x0
}
0804835f <main+0x2b> leave
08048360 <main+0x2c> ret
08048361 <main+0x2d> nop
08048362 <main+0x2e> nop
08048363 <main+0x2f> nop

[root@murmillo tmp]# ./a.out
Segmentation fault


P.S. Если хочешь выделять большие объекты на стеке, то рекомендую собирать с -fstack-check (stack overflow будет вылавливаться сразу).

Murr ★★
()
Ответ на: комментарий от Murr

В моем примере, правда, SEGFAULT приходит не поэтому, но если собрать с -fstack-check, то будет тот же SEGFAULT и уже как раз из-за переполнения стека.

Murr ★★
()
Ответ на: комментарий от Murr

2Murr: Спасибо,

а что скажешь касательно модулей. Если не в стэке размещать массив, а в области данных ядра, будут ли проблемы при копироавнии большего массива ядром в свою область данных!

Можно ли где-нибудь почитать про то, как ядро линкут данные модулей в свою область даннх?

anonymous
()
Ответ на: комментарий от anonymous

anonymous:

В ядре не рекомендуется на стеке размещать данные, т.к. стеки ядра - очень маленькие (одна или несколько страниц, при этом учитывай, что этот стек пользуют ядро выше модуля и могут использовать обработчики прерываний). В ядре все более-менее крупные структуры обычно выделяются динамически (alloc_pages, kmem_cache_alloc, page_cache_alloc). Данные, которые скомпонованы с модулем, подружаются modprobe (и сам код модуля) примерно так же, как это делает userspace run-time linker. Т.е. в принципе можно выделить массив в bss. 

В последнем случае только есть один нюанс. Насколько я помню (а кода ядра под рукой нет) код и данные модулей всегда отображаются через vmalloc и следовательно на _все_модули_ может быть отведено порядка 128 Мб.

anonymous
()
Ответ на: комментарий от anonymous

anonymous:

В ядре не рекомендуется на стеке размещать данные, т.к. стеки ядра - очень маленькие (одна или несколько страниц, при этом учитывай, что этот стек пользуют ядро выше модуля и могут использовать обработчики прерываний). В ядре все более-менее крупные структуры обычно выделяются динамически (alloc_pages, kmem_cache_alloc, page_cache_alloc). Данные, которые скомпонованы с модулем, подружаются modprobe (и сам код модуля) примерно так же, как это делает userspace run-time linker. Т.е. в принципе можно выделить массив в bss.

В последнем случае только есть один нюанс. Насколько я помню (а кода ядра под рукой нет) код и данные модулей всегда отображаются через vmalloc и следовательно на _все_модули_ может быть отведено порядка 128 Мб.

anonymous
()
Ответ на: комментарий от anonymous

anonymous:

В ядре не рекомендуется на стеке размещать данные, т.к. стеки ядра - очень маленькие (одна или несколько страниц, при этом учитывай, что этот стек пользуют ядро выше модуля и могут использовать обработчики прерываний). В ядре все более-менее крупные структуры обычно выделяются динамически (alloc_pages, kmem_cache_alloc, page_cache_alloc). Данные, которые скомпонованы с модулем, подружаются modprobe (и сам код модуля) примерно так же, как это делает userspace run-time linker. Т.е. в принципе можно выделить массив в bss.

В последнем случае только есть один нюанс. Насколько я помню (а кода ядра под рукой нет) код и данные модулей всегда отображаются через vmalloc и следовательно на _все_модули_ может быть отведено порядка 128 Мб.

Murr ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.