2014-01-07 2 views
6

У меня есть структура, в которой я бы хотел включить статическое хранилище. Это векторный тип на DSP, и случайное объявление его в стеке является распространенной ошибкой для пользователей, которая вызывает переполнение стека, проблемы с производительностью или и то, и другое. Насколько я знаю, это невозможно, но мне любопытно, знает ли кто-нибудь еще лучше.Принудительное статическое хранение во время компиляции

Пример использования:

static Vector64 v1; // OK 
static Vector64 v2; // OK 
static Vector64 result; // OK 
result = v1 * v2; // OK 

Vector64 v3; // I would like this to give a compile-time error 
Vector64 v4; 
result = v3 * v4; 

Мой компилятор Clang/LLVM 3.2 и атрибуты компилятора конкретных справедливая игра.

+0

Я знаю, как (с C++) разрешать только динамическое хранилище (предотвращать статические и автоматические) или предотвращать динамическое хранилище (разрешено только статическое и автоматическое), но я не считаю, что вы можете отличить статическую память от автоматического хранения продолжительность. –

+0

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

+0

Можете ли вы использовать собственное распределение кучи?Вы можете скрыть экземпляр 'Vector64' за фабрикой и создать полностью контролируемое хранилище кучи, используя специальный распределитель (при необходимости выровненный). – Drop

ответ

2

Поскольку C не имеет классов, я бы это в значительной степени допустил.

В общем, в C++, когда вы определяете класс, вы не можете контролировать, будет ли определить объекты этого типа static союзника, в стеке, в куче, const или нет const, в массиве или члена другого класса , Это выбор до пользователей этого класса.

Есть некоторые хитрости, чтобы держать его в кучу (например, играя с operator new), или только в куче (например, с использованием шаблона генератора), но это еще не то, что вы хотите

Я хотел бы видеть как это возможно, но до этого времени я уверен, что вы не можете.

+0

Вы можете переопределить оператор new в классе и объявить его закрытым. Это приведет к сбою компиляции, если есть какие-либо попытки распределения кучи. –

-2

Если вы программируете на C, у вас будут проблемы с этим. С C++ он должен работать. Я никогда не использовал этот компилятор, но в этих вопросах оба языка совершенно разные. Проверьте свой компилятор.

+0

Я отмечен как оба, потому что мне удобно использовать решение с любого языка. Обычно мы используем C++ 11, но мы строим из разных источников для любого отдельного проекта (ASM/C/C++) –

+1

Можете ли вы показать *, как это будет работать с C++? AFAIK, если это возможно, это неинтуитивно и будет очень сложно. –

+0

@GlennTeitelbaum, почему вы думаете, что это возможно? AFAIK это не так, но я бы хотел доказать, что это неправильно! –

2

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

Если вы знаете адресное пространство раньше времени, самое безопасное (по-языковому) - просто сравнить абсолютное положение стека.

struct Vector64 { 
    Vector64() { assert(reinterpret_cast<uintptr_t>(this) < STACK_START); } 
}; 

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

__attribute__((noinline)) Vector64() { 
    int test; 
    assert(less<void*>()(this, &test)); 
} 

Где __attribute__((noinline)) необходимо для предотвращения лязга от заказа выделения test до объекта Vector64 (или просто определить его в другом месте). С яркой стороны, оптимизация переупорядочения не может заставить это утверждать бросать ложный положительный результат, только терпеть неудачу молча. std::less также важен здесь, так как в отличие от < он явно позволяет сравнивать между адресами разных объектов.

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

Смежные вопросы