LINUX.ORG.RU

Безопасное использование функции alloca и определение размера стека

 , , ,


1

2

В C есть функция alloca, выделяющая память на стеке. Эта память автоматически освобождается при выходе из функции. При выделении чрезмерного количества памяти, происходит переполнение стека. Есть ли способ узнать, сколько памяти можно выделить в стеке? Хочется сделать что-то вроде такого:

if(в_стеке_хватит_места_чтобы_сделать_alloca(столько-то_байт) )
  tmp = alloca(столько-то_байт);
else
{
  tmp = malloc(столько-то_байт);
  if (tmp == NULL) 
    error();
  needfreetmp = 1;
}
...
какой-то_код;
...
if (needfreetmp)
  free(tmp)
И есть ли стандартный способ увеличить стек, например выделив достаточно большой кусок памяти через malloc, перекопировать туда весь используемый стек, переставить регистры EBP и ESP и дальше работать с этой памятью как со стеком?

★★★★★

Последнее исправление: cetjs2 (всего исправлений: 1)

alloca() is machine and compiler dependent; its use is discouraged.
beastie ★★★★★
()

В C некоторых реализациях рантайма C есть функция alloca

Починил.

Есть ли способ узнать, сколько памяти можно выделить в стеке?

man 2 getrlimit

И есть ли стандартный способ увеличить стек

man 2 setrlimit

например выделив достаточно большой кусок памяти через malloc, перекопировать туда весь используемый стек, переставить регистры EBP и ESP и дальше работать с этой памятью как со стеком?

Вот тут хз. Найти начало стека может быть сложно. Афаик, оно нигде явно не хранится, так что единственный вариант: пройтись по EBP-фреймам до начала. backtrace() так делает. Но компилятор может выкинуть эти фреймы, кто-то может свои выкрутасы делать в стеке, кто-то где-то может хранить указатели прям в стек и так далее.

Так что не думаю, что можно весь предшествующий стек гарантированно удачно перенести в другое место. Все последующие записи активаций укладывать в свой личный стек — думаю, вполне можно переместить. Ассемблером и платформоспецифично, естественно.

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

Если чё, можно создать новый тред со своим стеком

anonymous
()

В C есть функция alloca

4.2

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

Топик стартера видимо интересует ситуация

ptr = alloca(+100500 bytes);

Однако, в мане же написано:

...
The inlined code often consists of a single instruction adjusting the stack pointer, and does not check for stack overflow. Thus, there is no NULL error return.
...
If the allocation causes stack overflow, program behavior is undefined.

Dennis7
()

Идея говно. man c99 - конпелятор для кода вида buf[1005000] так и делает. man cleanup.

регистры EBP и ESP

Увеличить стек? НА 32битном убожестве?

Берёшь что-то типа:

void true_alloc(void) {
  static void * ptr = 0;
  return (ptr) ?: (ptr = mmap(1000500000));
}

И юзаешь это везде, если не идиот и не зафейлишь во вложенных функциях - будет работать в хлам илитно. Если идиот - пили на cleanup.

anonymous
()

Есть ли способ узнать, сколько памяти можно выделить в стеке?

rsp - pthread_attr_getstackaddr. Возможно, надо ещё учесть pthread_attr_getguardsize.

И есть ли стандартный способ увеличить стек

Можно тред создать с жирым стеком.

Пиши на C++, там scoped переменные есть. Или на Common Lisp.

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

или, в конце концов, запилить свой стековый аллокатор, даже на С можно сделать...

Главное не забыть man к нему написать

andreykyz ★★
()
typedef struct _alloc_t{
    void** allocs;
    int n;
} alloc_t;

alloc_t* create_alloc(){
    alloc_t* a = (alloc_t*)malloc(sizeof(alloc_t));
    a->n=0;
    a->allocs = malloc(sizeof(void*)*100);
    return a;
}

void free_alloc(alloc_t* a){
    while(a->n--){
        free(a->allocs[a->n]);
    }
    free(a->allocs);
    free(a);
}

void* alloc_with(alloc_t* a, size_t s){
    a->allocs[a->n] = malloc(s);
    a->n++;
    return a->allocs[a->n-1];
}

#define WITH_ALLOC(a) for(alloc_t* a = create_alloc(); a!=NULL; free_alloc(a),a=NULL)

int main(){
    WITH_ALLOC(a){
        int* x = alloc_with(a, 100*sizeof(int));
            .....
    }
}

Быдлокод, быдлокод! 100 malloc'ов должно хватить всем!

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