我如何知道指针是否已通过"新建"分配数据?
How do I know if a pointer has been assigned data via 'new'?
假设我有一个这样的指针:
int *thingy;
在某个时刻,这个代码可能被调用,也可能不被调用:
thingy=new int;
我如何知道我是否能做到这一点:
delete thingy;
我可以为每个指针使用bool
,并在每次使用new
时将布尔标记为true
,但我有很多指针,这会变得非常困难。
如果我没有在thingy
上调用new
,那么在它上面调用delete
可能会导致崩溃,对吧?
我找了很多遍,但都找不到符合我情况的答案。
编辑:我需要能够随心所欲地delete
指针,而指针不必指向任何数据。如果这是不可能的,我将不得不重新编写我的代码。
将其初始化为NULL始终
int *thingy = NULL;
然后
delete thingy;
thingy = NULL;
即使thingy为NULL也有效。只要thingy
是NULL
,delete
就不会有不必要的副作用,你可以随心所欲地删除。
没有内置的方法来判断特定的指针值是否可以delete
。相反,你只需要设计程序来做正确的事情,最好是根据你的需求仔细设计资源所有权政策,并用RAII之类的东西来实施。
给定适当的RAII类型,就不需要在代码中散布delete
或其他资源管理命令。您只需初始化并使用适当类型的对象,并将清理留给对象本身。例如,如果RAII类型unique_ptr
对应于您想要使用的所有权策略,那么您可以通过以下方式管理对象:
unique_ptr<int> thingy {new int};
// use thingy ...
不需要手动清理,因为unique_ptr
会为您处理这些问题。
另一方面,如果你试图直接管理资源,你最终会得到很多代码,比如:
int *thingy = nullptr;
// ...
thingy = new int;
try {
// something that might throw
} catch(...) {
delete thingy;
thingy = nullptr;
throw;
}
delete thingy;
thingy = nullptr;
没有内置的C++工具来识别指针是否指向堆数据,并且可以安全地delete
d。删除NULL指针是安全的,并且可以将数据已删除的每个指针设置为NULL。但这无助于区分指向堆数据的指针和指向其他数据或代码的指针。
当您的操作系统启动一个进程时,它会将代码和数据部分定位到特定的数据区域。在Windows中,这部分由EXE文件的PE头控制。因此,存储器区域的实际地址可以变化。但你可以确定这些区域的位置:
- 代码
- bss
- 数据
- 烟囱
- 堆
在获得每个区域的地址范围后,您可以区分指向堆数据的指针(在适合删除的情况下(和指向堆栈数据的指针。这允许您区分delete
表和指针不能删除的数据。
编写一个为您进行跟踪的包装类,例如:
template<typename T>
class ptr_t
{
private:
T* m_ptr;
bool m_delete;
ptr_t(const ptr_t&) {}
ptr_t& operator=(const ptr_t&) { return *this; }
public:
ptr_t()
: m_ptr(NULL), m_delete(false)
{
}
ptr_t(T *ptr, bool del)
: m_ptr(ptr), m_delete(del)
{
}
~ptr_t()
{
reset();
}
void assign(T *ptr, bool del)
{
if (m_delete)
delete m_ptr;
m_ptr = ptr;
m_delete = del;
}
void reset()
{
assign(NULL, false);
}
operator T*() { return m_ptr; }
bool operator!() const { return (!m_ptr); }
};
typedef ptr_t<int> int_ptr;
int_ptr thingy;
...
thingy.assign(new int, true);
...
thingy.reset();
int i;
int_ptr pi;
...
pi.assign(&i, false);
...
pi.reset();
- 将数组的地址分配给变量并删除
- vector.resize()中的分配错误
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- Win32编译器选项和内存分配
- 函数中堆分配的效果与缺少堆分配的情况
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 获取字符串的长度并将其分配给数组
- 将地址分配给本地指针后,公共对象的变量将消失
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存
- 我在二维向量中是否正确分配了内存
- 正在尝试重载二进制搜索树分配运算符
- GlobalAlloc而不是其他分配方法
- 自定义先决条件对移动分配运算符有效吗
- 我可以重新分配/覆盖std::字符串吗
- 分配新建的shared_ptr
- 通用内存分配崩溃,用于覆盖C++中的新建和删除
- 分配字符串时出现 char* 新建和删除 [] 错误
- 我如何知道指针是否已通过"新建"分配数据?