This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

 

  Object On The Stack
  Submitted by



isInStack(ptr) tests if an object pointed by ptr has been created to the stack or not. Motivation: When doing reference counting you want to assert you're not about to delete an object which has been allocated to the stack. Tested in following platforms:
  • MSVC6, Win2k
  • gcc 2.95.2, Win2k
  • gcc 2.95.2, Linux (RedHat)
  • gcc 2.8.1, Digital UNIX V4.0F


  • Makefile and MSVC6 project files are included.

    Known issues:
  • I haven't given any thought how this works in a shared library (dll/so)
  • Multithreading is supported only in Win32/MSVC


  • Jani Kajala PS. Why I didn't use !_CrtIsValidHeapPointer(p) of MSVCRT? 1) portability 2) coolness factor ;)


    Currently browsing [isInStack.zip] (3,545 bytes) - [isInStack.h] - (2,084 bytes)

    /*
     * isInStack 1.0
     * 
     * isInStack(ptr) tests if an object pointed by ptr
     * has been created to the stack or not.
     *
     * Motivation: When doing reference counting you 
     * want to assert you're not about to delete an object
     * which has been allocated to the stack.
     *
     * Tested in following platforms:
     * - MSVC6, Win2k
     * - gcc 2.95.2, Win2k
     * - gcc 2.95.2, Linux (RedHat)
     * - gcc 2.8.1, Digital UNIX V4.0F
     *
     * Makefile and MSVC6 project files are provided.
     *
     * Known issues:
     * - I haven't given any thought how this works in a shared library (dll/so)
     * - Multithreading is supported only in Win32/MSVC
     *
     * Feb 7, 2002,
     * Jani Kajala (jani.kajala@helsinki.fi)
     * 
     * PS.  Why I didn't use !_CrtIsValidHeapPointer(p) of MSVCRT?
     *      1) portability 2) coolness factor ;)
     */
    #ifndef _ISINSTACK_H
    #define _ISINSTACK_H

    /** * Initializes isInStack. * The init must be called in a higher level function than * where the isInitStack() is actually used. * * If multiple threads are used then the init needs to be called * at the beginning of each thread. Note that the thread function * calling isInStackInit must again be higher level than functions where * isInThread is actually used. */ void isInStackInit();

    /** * Returns true if the pointed object has been created in the stack * of the calling thread. */ bool isInStack( const void* p );

    /** Returns number of bytes of stack used by the calling thread. */ int usedStackSize();

    #endif // _ISINSTACK_H /* * Copyright (c) 2002 Jani Kajala * * Permission to use, copy, modify, distribute and sell this * software and its documentation for any purpose is hereby * granted without fee, provided that the above copyright notice * appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation. * Jani Kajala makes no representations about the suitability * of this software for any purpose. It is provided "as is" * without express or implied warranty. */

    Currently browsing [isInStack.zip] (3,545 bytes) - [isInStack.cpp] - (1,272 bytes)

    #include "isInStack.h"

    //------------------------------------------------------------------------ // thread local storage #ifdef _MSC_VER #define THREADLOCAL __declspec(thread) #else #define THREADLOCAL #endif

    //------------------------------------------------------------------------ /** Thread-specific stack bottom pointer. */ THREADLOCAL static const char* s_stackBottom = 0;

    //------------------------------------------------------------------------ static int getFrameSize( char* x ) { char y = 0; return x - &y; }

    void isInStackInit() { char x = 0; s_stackBottom = &x + getFrameSize(&x) * 2; }

    bool isInStack( const void* ptr ) { const char* p = (const char*)ptr; char x = 0; const char* stackTop = &x;

    if ( stackTop > s_stackBottom ) return p > s_stackBottom && p < stackTop; // stack grows up else return p > stackTop && p < s_stackBottom; // stack grows down }

    int usedStackSize() { char x = 0; const char* stackTop = &x;

    if ( stackTop > s_stackBottom ) return stackTop - s_stackBottom; // stack grows up else return s_stackBottom - stackTop; // stack grows down }

    Currently browsing [isInStack.zip] (3,545 bytes) - [test.cpp] - (1,042 bytes)

    #include "isInStack.h"
    #include <stdio.h>

    //------------------------------------------------------------------------ #define REQUIRE( A ) {if (!(A)) printf( "Assertion failed at %s(%i)\n", __FILE__, __LINE__ );}

    //------------------------------------------------------------------------ class MyClass { };

    //------------------------------------------------------------------------ static void func() { char testArray[123] = {0}; int size = usedStackSize(); printf( "usedStackSize in %s(%i) is %i\n", __FILE__, __LINE__, size );

    REQUIRE( isInStack(&size) ); REQUIRE( isInStack(testArray) ); }

    static void test() { char testArray[20] = {0}; MyClass a; MyClass* b = new MyClass; MyClass* c = new MyClass; MyClass d;

    func();

    REQUIRE( isInStack(&a) ); REQUIRE( !isInStack(b) ); REQUIRE( !isInStack(c) ); REQUIRE( isInStack(&d) );

    delete b; delete c; }

    int main() { isInStackInit(); test(); return 0; }

    The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

     

    Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
    Please read our Terms, Conditions, and Privacy information.