Prev: performance of hash_map in combination with strings on vstudio 2003
Next: Dot operator Overloading
From: James Kanze on 2 Apr 2010 07:03 On Apr 1, 3:04 pm, Goran <goran.pu...(a)gmail.com> wrote: > On Mar 31, 9:39 pm, pfultz2 <pful...(a)yahoo.com> wrote: > There is NO "neater way" but to KNOW, at any point in your > code, what you need to do with any object/variable. Note that in practice, most types will either be always allocated dynamically, or never allocated dynamically. There are exceptions, but they aren't that frequent. -- James Kanze -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: James Kanze on 2 Apr 2010 07:02 On Mar 31, 8:39 pm, pfultz2 <pful...(a)yahoo.com> wrote: > I want detect if a pointer is pointing to memory on the heap > or the stack, so I came up with this approach: > bool isOnHeap(void * p) > { > int i = 0; > int * s = &i; > return (p > s); > } > I dont if this is the best or most portable way to do it. It's not at all portable. It will work under Solaris on Sparc and Linux on PC (and probably Solaris on PC and Linux on Sparc). I don't think it will work for Windows, however, and it definitely will not work on HP/UX on PA. And of course, it will only work in a single threaded program. > And im not sure how well it works for static and global > variables, do they start on the end of memory? or at the > begining? Yes:-). There are no absolute rules. On machines where the hardware stack grows down (Intel, Sparc), most Unix systems will arrange the memory more or less like: +-------+ | stack | +-------+ <--- stack pointer | free | +-------+ | heap | +-------+ <--- end | bss | +-------+ | data | +-------+ | text | +-------+ With the data at the bottom, and a predefined symbol end at the top of the static variables. (Bss is the traditional name for static objects with no specified initialization: "data" gets copied from disk when the program is loaded, and "bss" gets set to 0.) But there's certainly nothing which guarantees this layout; it's probably more of a historical tradition than anything else. > The reason why i want to do this is need to delete pointers > sometimes, and some of them point to memory on the stack, so > therefore i dont want to delete them, The correct solution here is to use dynamic allocate systematically in cases where dynamic allocation might make sense, and to never take the address of an object. The unary & operator is something you should almost never use. -- James Kanze -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: James Kanze on 2 Apr 2010 07:11 On Apr 2, 5:02 pm, Mark Zaytsev <mark.zayt...(a)gmail.com> wrote: > On Apr 1, 10:03 am, George Neuner <gneun...(a)comcast.net> wrote: > > On Wed, 31 Mar 2010 13:39:59 CST, pfultz2 > > <pful...(a)yahoo.com> wrote: > > >I want detect if a pointer is pointing to memory on the > > >heap or the stack, so I came up with this approach: > [skip] > > The stack check works on Unix/Linux and Windows because > > their stacks are contiguous - but there may be other > > platforms for which it won't work (although I've yet to meet > > such a platform). > Stack of which thread ? > If object allocated on the other thread's stack, your check > will say: HEAP... Maybe, maybe not. If the function is called from another thread, it might also say STACK, when the data is actually on the heap. Of course, if you're working in a multithreaded environment, with all of the threads being started by some common function, and no objects are ever allocated from main, it's easy to see if an object is on the current thread's stack, some other thread's stack, or elsewhere, since you can control the addresses of the stacks. -- James Kanze -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: rado on 2 Apr 2010 07:10 On Mar 31, 12:39 pm, pfultz2 <pful...(a)yahoo.com> wrote: > I want detect if a pointer is pointing to memory on the heap or the > stack, so I came up with this approach: > > bool isOnHeap(void * p) > { > int i = 0; > int * s = &i; > return (p > s); > > } > > I dont if this is the best or most portable way to do it. And im not > sure how well it works for static and global variables, do they start > on the end of memory? or at the begining? The reason why i want to do > this is need to delete pointers sometimes, and some of them point to > memory on the stack, so therefore i dont want to delete them, I could > use type erasure and create a seperate class to handle the memory and > use some form of custom deallocators, but then it would either cost me > an extra pointer or double dereferencing, and i was trying to think of > a neater way to do it. thanks. { edits: quoted banner removed. please keep readers in mind when you quote. thank you. -mod } As others noted already, it is *not* possible, as per C++ standard. You just must *know* it; just the same way that you *know* what a function you are writing does. Beside that, though, I was wondering whether it is possible to develop such "address classification" facility IN PRACTICE. Here's how it can be done: For linear stacks (address ranges with no 'holes'), recognizing a stack variable is trivial, by just checking if it is in the range of the addresses. If similar property exists for addresses of global/ static objects, they can be recognized in a similar manner as well. What remain are the heap objects. Voila! Of course, such a facility should be better provided by the implementation, and is doomed to be nonportable. Now, is it good to have it though? It depends. If uses as a crutch for sloppy designers, NO. But it might be useful for debugging/diagnostics purposes, e.g. for signalling illegal 'delete' in better/more predictive way. Real world example: here's a function that I wrote: // ============================================================================== // Check if 'pVariable' is on the stack (of the current thread). // Neither portable nor 100% foolproof, but works in practice. // (The platform is Windows/MSVC.) // ________________________________________________________________________________________ bool isOnStack (const void* pVariable) { char k = 0; intptr_t nDiff = (char*) pVariable - &k; if (nDiff < 0) nDiff = -nDiff; bool bRet = nDiff < 30000; // Any other not-too-big-not-too-small magic number is good return bRet; } And I just found out that I only used it once (inside assert) in a project of several hundred thousand lines of code. This - to me - underlines again the limited utility of such things. -- Radoslav Getov -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: pfultz2 on 2 Apr 2010 10:24
On Apr 2, 7:46 am, Goran <goran.pu...(a)gmail.com> wrote: > On Apr 2, 9:36 am, pfultz2 <pful...(a)yahoo.com> wrote: > > > > > For example, if I have two classes like this: > > template<class T, int N> > > class value_array > > { > > T data[N]; > > > public: > > int length() > > { > > return N; > > > } > > > T* pointer() > > { > > return data; > > > } > > > //Methods for operator overloading > > > }; > > > template<class T> > > class array > > { > > int len; > > T* data; > > > public: > > explicit array(int n) > > { > > len = n; > > data = new T[N]; > > > } > > > template<int N> > > array(value_array<T, N>& a) > > { > > data = a.pointer(); > > len = N; > > > } > > > int length() > > { > > return N; > > > } > > > T* pointer() > > { > > return data; > > > } > > > void deallocate() > > { > > if (is_heap(data)) delete [] data; > > > } > > > //Methods for operator overloading > > > }; > > > This is kind of a rough sketch of what im trying to accomplish. > > Why not simply this: > > class array > { > // ... > bool _owns; > explicit array(int n) : _owns(true) > { > len = n; > data = new T[N]; > } > > template<int N> > array(value_array<T, N>& a) : _owns(false) > { > data = a.pointer(); > len = N; > } > ~array() > { // NB: you should probably forget your "deallocate" idea. > if (_owns) delete [] data; > } > > } > > But! But... I seriously question your design. > > Why do think you should have modifiable data in multiple arrays like > this? Do you actually want to mix them this way? From a design > standpoint, it seems mighty dubious to me. > > One reason I can think of why you would want that is that after > __serious__ performance measurement and a __serious__ work on > optimization (most notably, elimination of copying), you still need to > go faster. > > If, OTOH, you were thinking "it will be faster if I do it this way" > for no apparent reason... Just forget the whole idea and go for > std::vector. Honestly. Also, did you consider using shared_ptr? > > Goran. > > -- > [ Seehttp://www.gotw.ca/resources/clcm.htmfor info about ] > [ comp.lang.c++.moderated. First time posters: Do this! ] The problem with vector and shared_ptr, which would give the same semantics respectively, is first they are not a POD type. Secondly, I want to emulate the semantics that are in C, but have lenght available also. So there are two ways to create an array in C, 1) Create one dynamically, and use a pointer to it, or 2) Create one statically on the stack. Now, using my design I can pass arrays by value or by reference, like this: void fun1(array<int> a) { //Process array } int main(int argc, char** argv) { value_array<int, 5> a; fun1(a); } Now it works like this also, in C: void fun1(int* a, int len) { //Process array } int main(int argc, char** argv) { int a[5]; fun1(a, 5); } But the length is carried along with it and plus I can add begin() and end() methods to get the iterators(or rather pointers) for the array, which is the standard methods to call on containers. This only seems like the next logical step in C++, to use a class. The problem is when I want to create a managed version of the array class, for shared_array, its ok. Here is rough example: template<class T> class shared_array : public array<T> { private: share_count sc; //Similar to whats used in boost shared_ptr public: template<int N> shared_array(value_array<T, N> a) { data = a.pointer(); len = N; sc = share_count(data, null_deleter()); } explicit shared_array(int n) { data = new T[n]; len = n; sc = share_count(data, array_deleter()); } //Make the user decide for how to deallocate template<class D> shared_array(array<T> rhs, D deallocator) { data = a.pointer(); len = n; sc = share_count(data, deallocator); } }; But sometimes shared_array is too much, so it would be better to have unique_array: template<class T> class unique_array : public array<T> { template<int N> unique_array(value_array<T, N> a) { data = a.pointer(); //We shouldnt delete beacause its on the stack len = N; } explicit unique_array(int n) { data = new T[n];//We should delte because its on the heap len = n; } unique_array(array<T> rhs) { data = a.pointer(); //Maybe we delete or maybe not, this could be from the heap or the stack len = n; } //...create move constructors ~unique_array() { this->deallocate(); //How can I tell if this is on the stack or in the heap? } }; However, we dont know if the array should be deallocated or not. We could always carry a bool along with the array to know whether it is from the stack or heap,but it has extra overhead. and i thought there was an easy way to tell if the pointer is on the heap, or a Win32 or POSIX command that could tell you if it was on the heap or not. Thanks for the answers -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |