CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 20

Thread: pointer

  1. #1
    Join Date
    Apr 2002
    Posts
    60

    pointer

    How could I know if a pointer is on the stack or on heap?!
    (How could I know if a pointer was allocated with new or with a reference?)

  2. #2

    I don't think there is a way....

    Although I don't understand why you would need to know this, as unless you are receiving a pointer from a function that you did not write, you should know if the data pointed at by the pointer is on the stack or the heap.

    Why would you need to know?

  3. #3
    Join Date
    May 2002
    Location
    Russia
    Posts
    1,571
    it's simple!

    call _msize. if it return 0 or something like that - object in stack!

    Note. It's a Microsoft specific.

  4. #4
    Join Date
    Jun 2002
    Posts
    1,417
    When compiled for debug, _msize() produces an ASSERT if the object was not allocated with malloc() family of functions.

  5. #5
    Join Date
    Aug 2002
    Location
    VA, USA
    Posts
    137
    James,
    (How could I know if a pointer was allocated with new or with a reference?)
    I believe you mean an address operator - not a reference.

    That being said, I don't know any generic way you can tell whether a
    pointer contains an address to stack or heap memory.

    regards, willchop

  6. #6
    Join Date
    Apr 1999
    Posts
    27,449
    There is no generic C++ way to do this. This is covered in one of Scott Meyer's Effective C++ books (Effective C++ or More Effective C++, I don't remember which one).

    Since C++ doesn't assume that there is even a "stack", the answer to your question is highly system, compiler, and OS dependent.

    Regards,

    Paul McKenzie

  7. #7

    Small mistake....

    I didn't post this question.

    Not a big deal - but you typed James, and then quoted the poster of the question.

  8. #8
    Join Date
    Aug 2002
    Location
    VA, USA
    Posts
    137
    Sorry James!

    -willchop

  9. #9
    Join Date
    Aug 2002
    Location
    VA, USA
    Posts
    137
    it's simple!

    call _msize. if it return 0 or something like that
    This function appears to only keep track of the actual
    pointer to the memory allocated by malloc - not valid addresses
    within that block. For this reason the function may not provide
    accurate results.

    For example:

    Code:
    char* buffer = static_cast<char*>(malloc(1000 * sizeof(char)));
    if (!buffer) return;
    
    char* mid_buffer = buffer + 499;
    
    printf("sizeof buffer: %d\n", _msize(buffer));
    printf("sizeof mid_buffer: %d\n", _msize(mid_buffer));
    
    free(buffer);
    The mid_buffer is pointing to memory that was dynamically
    allocated, but _msize() fails to report so.

    regards, willchop

  10. #10
    Join Date
    Aug 2000
    Location
    New Jersey
    Posts
    968
    (How could I know if a pointer was allocated with new or with a reference?)
    You could either create a new operator for the specific object you want to check, or if it's for multiple objects, you could over write the global new operator.

    Within your new operator, you can update a global vector of pointers, and then LATER, check the vector to see if your pointer is listed in the vector.
    David Maisonave
    Author of Policy Based Synchronized Smart Pointer
    http://axter.com/smartptr


    Top ten member of C++ Expert Exchange.
    C++ Topic Area

  11. #11
    Join Date
    Aug 2000
    Location
    New Jersey
    Posts
    968
    Here's an example:

    #include <iterator>
    #include <new>
    #include <map>


    class foo {
    public:
    int x;
    void* operator new(size_t)
    {
    foo* ptr = ::new foo;
    FooPtrs[ptr] = 0;
    return ptr;
    }
    void operator delete(void* ptr)
    {
    FooPtrs.erase((foo*)ptr);
    :elete ptr;
    }
    void* operator new[] (size_t s)
    {
    foo* ptr = ::new foo[s];
    for(foo* p = ptr;p < ptr+s;++p)
    FooPtrs[p]=s;
    return ptr;
    }
    void operator delete[] (void* ptr)
    {
    size_t s = FooPtrs[(foo*)ptr];
    for(foo* p = (foo*)ptr;p < (foo*)ptr+s;++p)
    FooPtrs.erase(p);
    }
    static std::map<const foo*, size_t> FooPtrs;
    static bool IsCreatedByNew(const foo* ptr)
    {
    return (FooPtrs.find(ptr) != FooPtrs.end());
    }
    };

    std::map<const foo*, size_t> foo::FooPtrs;


    int main(int argc, char* argv[])
    {
    foo *pXa = new foo[5];
    foo *pX = new foo;
    foo NotPtr;
    foo NotPtrA[5];
    bool t1 = foo::IsCreatedByNew(pXa);
    pXa++;
    bool t2 = foo::IsCreatedByNew(pXa++);
    bool t3 = foo::IsCreatedByNew(pX);
    bool t4 = foo::IsCreatedByNew(&NotPtr);
    bool t5 = foo::IsCreatedByNew(&NotPtrA[0]);
    bool t6 = foo::IsCreatedByNew(&NotPtrA[2]);

    delete [] pXa;
    delete pX;
    bool t7 = foo::IsCreatedByNew(pX);
    bool t8 = foo::IsCreatedByNew(pXa++);
    return 0;
    }
    David Maisonave
    Author of Policy Based Synchronized Smart Pointer
    http://axter.com/smartptr


    Top ten member of C++ Expert Exchange.
    C++ Topic Area

  12. #12
    Join Date
    Aug 2000
    Location
    New Jersey
    Posts
    968
    Correction:

    Code:
    #include <iterator>
    #include <new>
    #include <map>
    
    class foo {
    public:
    	void*   operator new(size_t)
    	{
    		foo* ptr = ::new foo;
    		FooPtrs[ptr] = 0;
    		return ptr;
    	}
    	void      operator delete(void* ptr)
    	{
    		FooPtrs.erase((foo*)ptr);
    		::delete ptr;
    	}
    	void*   operator new[] (size_t s)
    	{
    		foo* ptr = ::new foo[s];
    		for(foo* p = ptr;p < ptr+s;++p)
    			FooPtrs[p]=s;
    		return ptr;
    	}
    	void      operator delete[] (void* ptr)
    	{
    		size_t s = FooPtrs[(foo*)ptr];
    		for(foo* p = (foo*)ptr;p < (foo*)ptr+s;++p)
    			FooPtrs.erase(p);
    	}
    	static std::map<const foo*, size_t> FooPtrs;
    	static bool IsCreatedByNew(const foo* ptr)
    	{
    		return (FooPtrs.find(ptr) != FooPtrs.end());
    	}
    };
    
    std::map<const foo*, size_t> foo::FooPtrs;
    
    
    int main(int, char**)
    {
    	foo *pXa = new foo[5];
    	foo *pX = new foo;
    	foo NotPtr;
    	foo NotPtrA[5];
    	bool t1 = foo::IsCreatedByNew(pXa);
    	pXa++;
    	bool t2 = foo::IsCreatedByNew(pXa++);
    	bool t3 = foo::IsCreatedByNew(pX);
    	bool t4 = foo::IsCreatedByNew(&NotPtr);
    	bool t5 = foo::IsCreatedByNew(&NotPtrA[0]);
    	bool t6 = foo::IsCreatedByNew(&NotPtrA[2]);
    		
    	delete [] pXa;
    	delete pX;
    	bool t7 = foo::IsCreatedByNew(pX);
    	bool t8 = foo::IsCreatedByNew(pXa++);
    	return 0;
    }
    David Maisonave
    Author of Policy Based Synchronized Smart Pointer
    http://axter.com/smartptr


    Top ten member of C++ Expert Exchange.
    C++ Topic Area

  13. #13
    Join Date
    Apr 2002
    Posts
    60
    thank you all
    Thanx...It works!

    How about a generic method? a template seems to be more accurate here...

  14. #14
    Originally posted by Axter
    Correction:

    Code:
    void*   operator new(size_t)
    {
    	foo* ptr = ::new foo;
    	FooPtrs[ptr] = 0;
    	return ptr;
    }
    I hope the compiler is smart enough not to call the constructor twice.

    First of all, you don't check if calling global new fails or not. But in this case, it's not safe to do what this overload of new does. If global new succeeds - the constructor is called for the object. This could be disastrous if the class allocates memory in it's default constructor. Because when the overloaded new returns and succeeded - it's calls the constructor again. As you know, the constructor is the first function called in an object's life - therefore the member variable (the pointer) that points at memory is thought of as 'garbage' by the 2nd call to the constructor. Therefore you have a memory leak.
    Last edited by JamesSchumacher; October 21st, 2002 at 07:19 PM.

  15. #15
    Join Date
    Aug 2000
    Location
    New Jersey
    Posts
    968
    If global new succeeds - the constructor is called for the object. This could be disastrous if the class allocates memory in it's default constructor. Because when the overloaded new returns and succeeded - it's calls the constructor again. As you know, the constructor is the first function called in an object's life - therefore the member variable (the pointer) that points at memory is thought of as 'garbage' by the 2nd call to the constructor. Therefore you have a memory leak.
    You're absolutely right. I assume the constructor would be called only when the global operator is called.

    I modified the code to use malloc and free instead. That will prevent the double constructor and double destructor calls.

    As this is just an example, I leave it up to the questioner to add extra required validation.

    Code:
    #include <iostream>
    
    #include <iterator>
    #include <new>
    #include <map>
    #include <stdlib.h>
    
    class foo {
    public:
    	foo()
    	{
    		++Qty;
    		std::cout << "Passing through constructor " << Qty << std::endl;
    	}
    	~foo()
    	{
    		--Qty;
    		std::cout << "Passing through destructor " << Qty << std::endl;
    	}
    	void*   operator new(size_t)
    	{
    		foo* ptr = (foo*)malloc(sizeof(foo));
    		FooPtrs[ptr] = 0;
    		return ptr;
    	}
    	void      operator delete(void* ptr)
    	{
    		FooPtrs.erase((foo*)ptr);
    		free(ptr);
    	}
    	void*   operator new[] (size_t s)
    	{
    		foo* ptr = (foo*)malloc(sizeof(foo)*s); 
    		for(foo* p = ptr;p < ptr+s;++p)
    			FooPtrs[p]=s;
    		return ptr;
    	}
    	void      operator delete[] (void* ptr)
    	{
    		free(ptr);
    		size_t s = FooPtrs[(foo*)ptr];
    		for(foo* p = (foo*)ptr;p < (foo*)ptr+s;++p)
    			FooPtrs.erase(p);
    	}
    	static std::map<const foo*, size_t> FooPtrs;
    	static bool IsCreatedByNew(const foo* ptr)
    	{
    		return (FooPtrs.find(ptr) != FooPtrs.end());
    	}
    	static int Qty;
    };
    int foo::Qty = 0;
    
    std::map<const foo*, size_t> foo::FooPtrs;
    
    void SomeFunction()
    {
    	foo *pX = new foo;
    	foo *pXa = new foo[5];
    	foo NotPtr;
    	foo NotPtrA[5];
    	bool t1 = foo::IsCreatedByNew(pXa);
    	pXa++;
    	bool t2 = foo::IsCreatedByNew(pXa++);
    	bool t3 = foo::IsCreatedByNew(pX);
    	bool t4 = foo::IsCreatedByNew(&NotPtr);
    	bool t5 = foo::IsCreatedByNew(&NotPtrA[0]);
    	bool t6 = foo::IsCreatedByNew(&NotPtrA[2]);
    		
    	delete pX;
    	pXa--;
    	pXa--;
    	delete [] pXa;
    	bool t7 = foo::IsCreatedByNew(pX);
    	bool t8 = foo::IsCreatedByNew(pXa++);
    }
    
    
    int main(int, char**)
    {
    	SomeFunction();
    	return 0;
    }
    David Maisonave
    Author of Policy Based Synchronized Smart Pointer
    http://axter.com/smartptr


    Top ten member of C++ Expert Exchange.
    C++ Topic Area

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured