C++ 重新分配堆栈和堆指针的内存
我开发了一个阻塞队列类,如下所示C++ 重新分配堆栈和堆指针的内存,c++,heap-memory,stack-memory,memory-reallocation,C++,Heap Memory,Stack Memory,Memory Reallocation,我开发了一个阻塞队列类,如下所示 class Blocking_queue { public: Blocking_queue(); int put(void* elem, size_t elem_size); int take(void* event); unsigned int get_size(); private: typedef struct element { void* elem; size_t
class Blocking_queue
{
public:
Blocking_queue();
int put(void* elem, size_t elem_size);
int take(void* event);
unsigned int get_size();
private:
typedef struct element
{
void* elem;
size_t elem_size;
struct element* next;
}element_t;
std::mutex m_lock;
std::condition_variable m_condition;
unsigned int m_size;
element_t* m_head;
element_t* m_tail;
};
我希望该类尽可能通用,因此我使用一个void指针,当元素添加到队列中时分配该指针,从队列中删除时释放该指针
int Blocking_queue::take(void* event)
{
element_t* new_head = NULL;
int ret = 0;
// Queue empty
if(nullptr == m_head)
{
// Wait for an element to be added to the queue
std::unique_lock<std::mutex> unique_lock(m_lock);
m_condition.wait(unique_lock);
}
if(nullptr == realloc(event, m_head->elem_size))
{
ret = -1;
}
else
{
// Take element from queue
memcpy(event, m_head->elem, m_head->elem_size);
ret = m_head->elem_size;
new_head = m_head->next;
free(m_head->elem);
free(m_head);
m_head = new_head;
if(nullptr == m_head)
{
m_tail = nullptr;
}
m_size -= 1;
}
return ret;
}
我将在realloc上出现无效的旧尺寸错误
因此,如果我传递一个空指针或一个堆分配的变量,它将工作,但如果我传递一个堆栈变量地址,它将不工作
是否有一种方法允许将堆栈变量地址传递给take()
函数?
有没有一种方法允许将堆栈变量地址传递给take()呢
功能
简而言之,答案是否定的。malloc()
/free()
/realloc()
只能使用堆分配的内存;它们不能使用堆栈分配的内存
至于如何解决这个问题,我认为需要重新设计。我的第一个建议是尽可能远离(void*)
——void指针是非常不安全的,很难正确使用,因为编译器不知道它们指向什么,因此当程序员错误地执行某些操作时,无法生成错误;这会导致许多运行时问题。它们更像是C语言构造,在C++中仍然支持C兼容性,但是C++有更好和更安全的方法来做同样的事情。
特别是,如果您的队列的所有数据元素都应该是相同的类型,那么显然要做的事情是使用该类型作为模板参数对阻塞队列类进行模板化;然后用户可以指定例如Blocking_queue
并使用他喜欢的任何类型,并提供易于使用的按值语义(类似于例如std::vector
和friends提供的语义)
如果您想允许混合不同类型的数据元素,那么最好的方法是再次执行上述操作,但要为对象定义一个公共基类,然后您可以实例化一个Blocking_queue
对象,该对象将接受指向该基类任何子类的任何堆分配对象的共享指针。(如果确实需要将共享指针传递给堆栈分配的对象,可以通过为共享指针定义自定义分配器来实现,但请注意,这样做会打开对象生命周期不匹配问题的大门,因为堆栈对象可能在从队列中移除之前被销毁)如果有问题,请不要这样做。您的设计是错误的。<代码> TyPufFraseEngult——在C++中不需要<代码> TyBuffsStult。您只需要struct元素
。其次,我希望类尽可能通用——如果元素是非POD类型,例如std::string
,那么类将如何工作?使用malloc
,realloc
等将不起作用。这看起来是一个尝试使用<代码> C++ <代码>构造,期望 > c>代码>与C++ W.R.T的工作方式相同,动态创建实例并处理这些实例。“通用”是在C++中通过使用模板实现的。
void function()
{
unsigned int event = 0;
queue->take(&event);
}