-2

Possible Duplicate:
C++ - Check if pointer is pointing to valid memory (Can't use NULL checks here)

How to check if pointer is valid without a wrapper or additional memory attached to him? By valid I mean that I didn't deleted it or I can reach it or It allocated.

I am using VS\Windows.

Community
  • 1
  • 1
MessyCode
  • 333
  • 1
  • 2
  • 9

2 Answers2

1

A pointer is valid if "you didn't deleted that or this memory is allocated or at al you can access that memory". So I suggest:

  1. Keep track of memory you have allocated. If this pointer is not in any of those blocks, you didn't allocate it.

  2. When you delete a pointer or free memory, remove it from the list. That way, you can also check that you didn't delete it.

  3. Try to access it. If you can't access it, it's not valid.

  4. If it passes these tests, it's valid.

I am not joking. The right way to do this is to precisely define what you mean by "valid" and precisely test whether the pointer meets those conditions.

But really, this is just not how C++ is done. Whatever your underlying issue is, there's probably a better way to do it.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • Check if pointer is in the list is very heavy (I am creating scripting language) and I mentioned that I don't want additional data with the pointer. (Can be parallel list and etc.) – MessyCode Aug 03 '12 at 14:23
  • @MessyCode: If checking the list is heavy, optimize it. For example, you can use Boost's [unordered_map](http://www.boost.org/doc/libs/1_48_0/doc/html/boost/unordered_map.html) template. I don't understand why you don't want additional data with the pointer since your question specifically asks for additional data (whether the pointer is valid). – David Schwartz Aug 03 '12 at 14:28
  • I asked without additional data. But I think I alright answered my question. (Search for it maybe down there) – MessyCode Aug 03 '12 at 14:32
-3

This valid check checked in windows only (VS),here is the function:

#pragma once
//ptrvalid.h
__inline bool isValid(void* ptr) {
    if (((uint)ptr)&7==7)
        return false;
    char _prefix;
    __try {
        _prefix=*(((char*)ptr)-1);
    } __except (true) {
        return false;
    }
    switch (_prefix) {
    case 0:    //Running release mode with debugger
    case -128: //Running release mode without debugger
    case -2:   //Running debug mode with debugger
    case -35:  //Running debug mode without debugger
        return false;
        break;
    }
    return true;
}

Usage:

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

void PrintValid(void* ptr) {
    if (isValid(ptr))
        printf("%d is valid.\n",ptr);
    else
        printf("%d is not valid.\n",ptr);
}

int main() {
    int* my_array=(int*)malloc(4);
    PrintValid(my_array);
    PrintValid((void*)99);
    free(my_array);
    PrintValid(my_array);
    my_array=new int[4];
    PrintValid(my_array);
    delete my_array;
    PrintValid(my_array);
    getchar();
}

Output:

764776 is valid.
99 is not valid.
764776 is not valid.
774648 is valid.
774648 is not valid.

Function's explanation: (What it does)

The functions check before the real checking ,if the address is valid\start point to memory. After that he checks if this process can reach this memory's prefix (If caught exception if can't) and the last checking is checking what the prefix of this memory if deleted at any mode. (Debugging\Without Debug Mode\Release Mode) If the function passed all of those checks ,it returns true.

MessyCode
  • 333
  • 1
  • 2
  • 9
  • Now what if I want to use [TCMalloc](http://gperftools.googlecode.com/svn/trunk/doc/tcmalloc.html) :) – Joe Aug 03 '12 at 14:15
  • I tested it on new delete and malloc free and only on windows. I'll check tcmalloc later. I never heard of it. – MessyCode Aug 03 '12 at 14:18
  • I was just making a point that there is no standard way of doing this. Doing so relies on the implementation details of the allocater and therefore it will never be portable. It is nice, however, to see how to do it on windows using VS. – Joe Aug 03 '12 at 14:23
  • 4
    `char array[] = { -128, 10 }; char *p = &array[1]; PrintValid(p);` => false. `struct X { double d; char array[10]; }; X x; PrintValid( &x.array[7]);` => false. Probably other false positives/false negatives. – David Rodríguez - dribeas Aug 03 '12 at 14:24
  • @Joe OK I'll check your TCMalloc :(. – MessyCode Aug 03 '12 at 14:24
  • @DavidRodríguez-dribeas It's failed because you gave invalid address. Valid address is what returns from allocate function. BTW you can hack it when you make array with 8 items and and skip to the last item. – MessyCode Aug 03 '12 at 14:26
  • @Joe I can't test it ,I don't have Windows. Can you check it for me :D? – MessyCode Aug 03 '12 at 14:28
  • @DavidRodríguez-dribeas Only address that dividable with 8 is allowed. To block you :D try: `delete &x.array[7];` if deletes it'll give you memory leak or something wrong. (?) – MessyCode Aug 03 '12 at 14:30
  • @MessyCode: You have a very particular interpretation of what a valid pointer is. In the code above the pointers were all *valid* according to the standard, and they can be used for anything other than releasing the memory. Of course if the question is 'how can I detect that a pointer has been acquired from the MS VS default allocator in windows and has never been released back to the system' then this could be an option. For any other question, this is not an answer. – David Rodríguez - dribeas Aug 03 '12 at 14:35
  • @MessyCode: So a pointer to an element of an array isn't valid? It wasn't deleted. You can reach it. By the definition of "valid" in the question, a pointer to every element of an array of characters is valid. "*By valid I mean that I didn't deleted it or I can reach it or It allocated.*" – David Schwartz Aug 03 '12 at 14:35
  • @DavidSchwartz I mean the first pointer that you received when you allocated that memory. – MessyCode Aug 03 '12 at 14:40
  • `char data[16] = { 0, 0, 0, 0, 0, 0, 0, 1 }; PrintValid( &data[8] );` => true, when clearly it cannot be deleted, so the scope of your function is even more limited, as it will tell you that you can `delete` that pointer, while that is not the case. – David Rodríguez - dribeas Aug 03 '12 at 14:41
  • 3
    -1. The main problem with this code is that you seem to have gotten your "facts" about preceding byte values from a few tests, which doesn't tell you anything about the general case. For Debug mode, there are indeed specific byte values before and after the allocated block (see http://msdn.microsoft.com/en-us/library/bebs9zyz%28v=vs.90%29.aspx) but for Release mode, these bytes **could be anything** and you cannot rely on them being anything in particular. Separately, there's a bug: operator precedence means the test `((uint)ptr)&7==7` actually tests `(((uint)ptr) & (7==7)`. – j_random_hacker Aug 03 '12 at 14:44
  • @j_random_hacker Didn't caught it. Thanks. I debugged the assembly of free to see how he is checking if memory is valid. Then I remake it to C++ to you people to understand how it works. – MessyCode Aug 03 '12 at 15:01