Mar*_*aux 27 c++ pointers memory-management
例:
bool isHeapPtr(void* ptr)
{
//...
}
int iStack = 35;
int *ptrStack = &iStack;
bool isHeapPointer1 = isHeapPtr(ptrStack); // Should be false
bool isHeapPointer2 = isHeapPtr(new int(5)); // Should be true
/* I know... it is a memory leak */
Run Code Online (Sandbox Code Playgroud)
如果我在一个类中有一个成员指针,我不知道指向对象是否是新分配的.然后我应该使用这样的实用程序来知道我是否需要delete
指针.
但是:
我的设计尚未完成.所以,我会按照我一直以来的方式编程delete
.我要避免垃圾编程
小智 30
没有办法做到这一点 - 如果你需要这样做,你的设计就会出现问题.讨论了为什么你不能在更有效的C++中做到这一点.
Car*_*rum 15
在一般情况下,你很运气,我很害怕 - 因为指针可以有任何价值,所以没有办法区分它们.如果您了解堆栈的起始地址和大小(例如,从嵌入式操作系统中的TCB),您可能能够做到这一点.就像是:
stackBase = myTCB->stackBase;
stackSize = myTCB->stackSize;
if ((ptrStack < stackBase) && (ptrStack > (stackBase - stackSize)))
isStackPointer1 = TRUE;
Run Code Online (Sandbox Code Playgroud)
Eva*_*ran 12
我能想到的唯一"好"解决方案是operator new
为该类重载并跟踪它.像这样的东西(脑编译代码):
class T {
public:
void *operator new(size_t n) {
void *p = ::operator new(n);
heap_track().insert(p);
return p;
}
void operator delete(void* p) {
heap_track().erase(p);
::operator delete(p);
}
private:
// a function to avoid static initialization order fiasco
static std::set<void*>& heap_track() {
static std::set<void*> s_;
return s_;
}
public:
static bool is_heap(void *p) {
return heap_track().find(p) != heap_track().end();
}
};
Run Code Online (Sandbox Code Playgroud)
然后你可以做这样的事情:
T *x = new X;
if(T::is_heap(x)) {
delete x;
}
Run Code Online (Sandbox Code Playgroud)
但是,我会建议不要让你能够询问是否在堆上分配了某些东西.
好吧,拿出你的汇编书,并将指针的地址与堆栈指针进行比较:
int64_t x = 0;
asm("movq %%rsp, %0;" : "=r" (x) );
if ( myPtr < x ) {
...in heap...
}
Run Code Online (Sandbox Code Playgroud)
现在x将包含您必须将指针与之比较的地址.请注意,它不适用于在另一个线程中分配的内存,因为它将拥有自己的堆栈.
在这里,适用于MSVC:
#define isheap(x, res) { \
void* vesp, *vebp; \
_asm {mov vesp, esp}; \
_asm {mov vebp, ebp}; \
res = !(x < vebp && x >= vesp); }
int si;
void func()
{
int i;
bool b1;
bool b2;
isheap(&i, b1);
isheap(&si, b2);
return;
}
Run Code Online (Sandbox Code Playgroud)
它有点难看,但有效.仅适用于局部变量.如果从调用函数传递堆栈指针,则此宏将返回true(表示它是堆)
小智 5
即使您可以确定指针是位于一个特定堆上还是一个特定堆栈上,一个应用程序也可能存在多个堆和多个堆栈。
根据询问的原因,对于每个容器来说,对于它是否“拥有”它所持有的指针有严格的政策是极其重要的。毕竟,即使这些指针指向堆分配的内存,其他一些代码也可能拥有同一指针的副本。尽管所有权可以转移,但每个指针一次应该有一个“所有者”。业主负责销毁。
在极少数情况下,容器跟踪拥有的和非拥有的指针很有用——可以使用标志,也可以单独存储它们。不过,大多数时候,为任何可以保存指针的对象设置明确的策略会更简单。例如,大多数智能指针始终拥有其容器真实指针。
当然,智能指针在这里很重要 - 如果您想要一个所有权跟踪指针,我相信您可以找到或编写一个智能指针类型来抽象化这个麻烦。