我遇到了在不同线程(TI F28379D)上发生的新/删除问题,如果在分配或删除过程中发生中断,导致程序锁定。我不想用一个禁用和启用中断的宏来包装new / delete的每个实例,因为它感觉像是很多重复的代码。我的解决方案是创建两个函数,这些函数在new / delete周围有适当的宏。
void *create_array_pointer(uint16_t count, size_t size, char *variable_name) {
//create the array (inside where interrupts are disabled
uint16_t interrupt_settings = __disable_interrupts();
void *ptr = new uint16_t[count*size];
__restore_interrupts(interrupt_settings);
check_allocation_throw_error(ptr, variable_name);
return ptr;
}
void delete_array_pointer(void *ptr) {
uint16_t interrupt_settings = __disable_interrupts();
delete[] ptr;
ptr = NULL;
__restore_interrupts(interrupt_settings);
}
这适用于原始类型。但是,我今天意识到这对于具有默认构造函数/析构函数的c ++类来说是一个糟糕的解决方案,因为构造函数或析构函数永远不会被自动调用。
是否有某种方法可以确保调用构造函数/析构函数,而无需返回包装每个调用?
答案 0 :(得分:2)
我假设您处于无法使用容器或智能指针的环境中。否则,我建议您返回std::vector
或std::unique_ptr
。
您可以使用模板保留正在创建的对象的类型,同时仍然是泛型。
此外,您可能需要考虑采用RAII
方式来管理中断,因为它们将是异常安全的,并且通常更安全,更容易:
template<typename T>
void check_allocation_throw_error(T*, char const*) {}
// This will disable interrupts on creation and re-enable them
// when it goes out of cope. This means if you reach the end
// of the function OR if an exception is thrown the interrupts
// will be re-enabled regardless.
class interrupt_disabler
{
public:
interrupt_disabler(): settings(__disable_interrupts()) {}
~interrupt_disabler() { __restore_interrupts(settings); }
private:
interrupt_disabler(interrupt_disabler const&) {}
interrupt_disabler& operator=(interrupt_disabler const&) { return *this; }
uint16_t settings;
};
template<typename T>
T* create_array_of(uint16_t count, char const* variable_name)
{
T* ptr = 0;
// create a scope where interrupts are disabled
{
interrupt_disabler lock(); // enabled at end of scope OR if new throws
ptr = new T[count];
}
// interrupts enabled automatically here
check_allocation_throw_error(ptr, variable_name);
return ptr;
}
template<typename T>
void delete_array(T* ptr)
{
interrupt_disabler lock(); // enabled at end of scope
delete[] ptr;
}
struct MyType {}; // any old type
int main()
{
MyType* mytype = create_array_of<MyType>(10, "wibble");
delete_array(mytype);
}