В процессе тестирования и анализа большой базы кода мне приходится заменять тысячи вызовов alloca() собственным методом. На моей целевой платформе alloca() не работает, если число равно нулю, поэтому мы хотим утверждать, что это так. Мы также хотим предоставить версию выравнивания, которая является одним вызовом. Однако alloca() имеет определенное время жизни, связанное с областью действия, поэтому, хотя я хотел бы написать
void * CheckAndAllocate( size_t sizeInBytes )
{
assert( sizeInBytes > 0 );
return alloca(p); // not safe; allocation goes out of scope on return
}
void * p = CheckAndAllocate( sizeInBytes );
Очевидно, что это не вариант, поскольку alloca() не переживет CheckAndAllocate().
Пытаясь решить эту проблему, я написал эту альтернативу, используя временную:
struct CheckSize
{
inline CheckSize( size_t size ) { assert( size > 0 ); }
inline void * operator=(void* other) { return other );
}
#define my_alloca(size) CheckSize(size) = alloca(size)
void foo(size_t size)
{
void * p = my_alloca(size);
// becomes
void * p = CheckSize(size) = alloca(size);
// ... use p locally for work
}
Кроме того, я также определил свою выровненную версию как:
struct CheckSizeAndAlign
{
size_t _align;
inline CheckSizeAndAlign( size_t size, size_t align ) : _align(align) { assert( size > 0 ); }
inline void * operator=(void* other) { return AlignUp(other, _align ); }
#define my_alloca_aligned( size, align ) CheckSizeAndAlign(size, align ) = alloca(size + align)
void foo(size_t size, size_t alignment)
{
void * p = my_alloca_aligned( size, alignment);
// becomes
void * p = CheckSizeAndAlign( size, alignment) = alloca( size + alignment )
// ... use p locally for work
}
Мой вопрос: учитывая, что значение, возвращаемое alloca, проходит через временное, нарушает ли это выделение alloca из-за какой-либо области видимости?
Я понимаю, что вокруг alloca есть подводные камни, и что есть несколько решений, чтобы исправить это, но я надеюсь внедрить эти изменения в кодовую базу, ничего не меняя, а просто добавив некоторую диагностику.
Мне также просто любопытно узнать об этом конкретном шаблоне.
Это MSVC2019, CLANG и нишевые компиляторы систем реального времени.
alloca
не является стандартной функцией, и ее поведение может различаться у разных поставщиков. - person 1201ProgramAlarm   schedule 24.04.2020thousands of calls to alloca()
Мне интересно - почему было принято решение использоватьalloca()
вместо динамического размещения и интеллектуальных указателей? - person KamilCuk   schedule 24.04.2020alloca(CheckSize(size))
- и избежать дублирования размера. ЗатемCheckSize
может иметь утверждение (или любую другую проверку, которую вы хотите) и возвращать (возможно, измененный) параметр, чтобы избежать неправильного вызоваalloca(0)
(хотя некоторые библиотеки с этим согласны). - person 1201ProgramAlarm   schedule 24.04.2020