Можно ли предсказать переполнение стека в C на Linux? - PullRequest
4 голосов
/ 09 января 2009

Существуют определенные условия, которые могут вызвать переполнение стека в системе Linux x86:

  • struct my_big_object[HUGE_NUMBER] в стеке. Проходя через это в конечном итоге вызывает
  • Подпрограмма alloca() (как и malloc(), но использует стек, автоматически освобождает себя, а также взрывается с SIGSEGV, если она слишком большая). Обновление: alloca () формально не устарела, как я изначально говорил; это просто обескуражено .

Есть ли способ программно определить, достаточно ли велик локальный стек для данного объекта? Я знаю, что размер стека регулируется с помощью ulimit, поэтому я надеюсь, что есть способ (каким бы непереносимым он ни был). В идеале я хотел бы иметь возможность сделать что-то вроде этого:

int min_stack_space_available = /* ??? */;
if (object_size < min_stack_space_available)
{
    char *foo = alloca(object_size);
    do_stuff(foo);
}
else
{
    char *foo = malloc(object_size);
    do_stuff(foo);
    free(foo);
}

Ответы [ 12 ]

0 голосов
/ 09 января 2009

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

Что касается проблемы со стеком, вы можете попытаться выделить объекты динамически из фиксированного пула, который обнаруживает эти переполнения. С помощью простого макро-мастера вы можете запустить его во время отладки, с реальным кодом, выполняемым во время выпуска, и, таким образом, знать (по крайней мере, для сценариев, которые вы выполняете), что вы не берете слишком много. Вот дополнительная информация и ссылка на пример реализации.

0 голосов
/ 09 января 2009

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

bool CanFitOnStack( size_t num_bytes )
{
    int stack_offset_for_function = 4; // <- Determine this
    try
    {
        alloca( num_bytes - stack_offset_for_function );
    }
    catch ( ... )
    {
        return false;
    }

    return true;
}
...