88

Can we check whether a pointer passed to a function is allocated with memory or not in C?

I have wriiten my own function in C which accepts a character pointer - buf [pointer to a buffer] and size - buf_siz [buffer size]. Actually before calling this function user has to create a buffer and allocate it memory of buf_siz.

Since there is a chance that user might forget to do memory allocation and simply pass the pointer to my function I want to check this. So is there any way I can check in my function to see if the pointer passed is really allocated with buf_siz amount of memory .. ??

EDIT1: It seems there is no standard library to check it .. but is there any dirty hack to check it .. ??

EDIT2: I do know that my function will be used by a good C programmer ... But I want to know whether can we check or not .. if we can I would like to hear to it ..

Conclusion: So it is impossible to check if a particular pointer is allocated with memory or not within a function

sashoalm
  • 75,001
  • 122
  • 434
  • 781
codingfreak
  • 4,467
  • 11
  • 48
  • 60
  • 3
    I don't really think so, but I don't feel confident enough to post as an answer. – Ibrahim Oct 16 '09 at 05:48
  • There's no way to check, unless you use a memory manager or roll your own. – Michael Foukarakis Oct 16 '09 at 05:55
  • If its a character pointer, we can do strlen() or sizeof() and check how much memory is allocated(ofcourse if the string is NULL terminated). For other types, i am not sure if there is some way.!! – Sandeep Feb 18 '14 at 05:33
  • I know this is an old question, but it is possible to keep track of allocated memory without using hacks. My code below gives a few snippets to get you started. – c1moore Apr 25 '16 at 00:30
  • 1
    The conclusion that should be drawn is that you *shouldn't* check even if it was possible. [This article](http://blogs.msdn.com/b/oldnewthing/archive/2006/09/27/773741.aspx) explains the issue. While written in Windows term, the issue isn't Windows-specific. – ikegami May 17 '19 at 00:21
  • While the asker's use-case is inadvisable, there are at least a _few_ valid situations for doing this. For example, a complex codebase you've inherited has a difficult-to-diagnose segfault in a frequently run method, and runs on an embedded runtime that you can't attach to a debugger - detecting the bad pointer allows you to log diagnostic information needed to isolate the issue without logging excessively. – M-Pixel Jun 26 '19 at 20:15
  • While I *could* imagine some weird ways to accomplish that (the 'cleanest' would be to implement your own memory allocation functions and make the `malloc` , `free` etc. calls be replaced with calls to your routines), all of them would affect the entire program (they would have to), and are really dirty hacks if you don't want to change the calls in the source code of your entire program. I would refrain from that. It's common in C to pass in pointers to functions that are assumed to having been allocated in advance. – Michael Beer Jun 18 '20 at 12:51
  • BTW: There are tools that replace calls to mem allocating functions to track for memleaks / illegal mem accesses at runtime - `valgrind` being an easy one to use. If it's for testing your own code, just use one of these memcheckers. – Michael Beer Jun 18 '20 at 12:54

19 Answers19

43

You cannot check, except some implementation specific hacks.

Pointers have no information with them other than where they point. The best you can do is say "I know how this particular compiler version allocates memory, so I'll dereference memory, move the pointer back 4 bytes, check the size, makes sure it matches..." and so on. You cannot do it in a standard fashion, since memory allocation is implementation defined. Not to mention they might have not dynamically allocated it at all.

You just have to assume your client knows how to program in C. The only un-solution I can think of would be to allocate the memory yourself and return it, but that's hardly a small change. (It's a larger design change.)

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • A pointer could be not null but still not have buf_siz bytes allocated. I don't think there's really any way to check what the asker wants. – Ibrahim Oct 16 '09 at 05:49
  • 1
    Ok, how about this? Since this is C, the client probably used `malloc` which does return a `NULL` pointer if it were unable to allocate memory. So ... in `malloc` we trust? – Jacob Oct 16 '09 at 05:56
  • It's up to the client to make sure malloc worked before calling the function, if that's what you're saying. – GManNickG Oct 16 '09 at 05:57
  • @jacob - I do know that we can check down at malloc ... but if the client forget to do malloc then it results in segmentation fault .. and i want to avoid it. – codingfreak Oct 16 '09 at 06:01
  • No, what I'm saying is if the client used `malloc` it would return NULL if it couldn't allocate memory. Of course, that doesn't stop the client from passing a pointer which wasn't even used with `malloc` ... never mind. – Jacob Oct 16 '09 at 06:02
  • 9
    Yea. The end conclusion is your function should do one thing and one thing only. Imagine the overhead if every function made sure the memory it was accessing from parameters was valid. Just have your function do what it's suppose to do. – GManNickG Oct 16 '09 at 06:04
  • @GMan - Yeah I do agree with you ... but I want to know whether I can do it or not ... I know that my function will be used by a good C programmer and so on ... I got this doubt on whether checking is possible or not ... It is not wrong in knowing things we dont know – codingfreak Oct 16 '09 at 07:41
  • The answer is you *could* but it wouldn't follow any standard. – GManNickG Oct 16 '09 at 07:47
  • This is under-appreciated, probably since it's not the answer most wanted to hear. –  Aug 29 '16 at 11:40
10

The below code is what I have used once to check if some pointer tries to access illegal memory. The mechanism is to induce a SIGSEGV. The SEGV signal was redirected to a private function earlier, which uses longjmp to get back to the program. It is kind of a hack but it works.

The code can be improved (use 'sigaction' instead of 'signal' etc), but it is just to give an idea. Also it is portable to other Unix versions, for Windows I am not sure. Note that the SIGSEGV signal should not be used somewhere else in your program.

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <signal.h>

jmp_buf jump;

void segv (int sig)
{
  longjmp (jump, 1); 
}

int memcheck (void *x) 
{
  volatile char c;
  int illegal = 0;

  signal (SIGSEGV, segv);

  if (!setjmp (jump))
    c = *(char *) (x);
  else
    illegal = 1;

  signal (SIGSEGV, SIG_DFL);

  return (illegal);
}

int main (int argc, char *argv[])
{
  int *i, *j; 

  i = malloc (1);

  if (memcheck (i))
    printf ("i points to illegal memory\n");
  if (memcheck (j))
    printf ("j points to illegal memory\n");

  free (i);

  return (0);
}
Peter
  • 187
  • 1
  • 5
  • 3
    @Saco `i = malloc(1);` is valid C code and preferable to `i = (int*) malloc(1);`. Perhaps you are thinking of another language. – chux - Reinstate Monica Sep 19 '17 at 23:05
  • Note under POSIX, `setjmp()` and `longjmp()` should probably be replaced with [`sigsetjmp()`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigsetjmp.html) and [`siglongjmp()`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/siglongjmp.html). See https://stackoverflow.com/questions/20755260/why-sigsetjmp-is-using-instead-setjmp-function-in-c – Andrew Henle Apr 01 '19 at 14:24
  • 1
    IMHO, there is no guarantee that an invalid memory access will cause a SEGV - your `c = *(char *)(x);` might pass just fine, even though `x` does not point to an allocated area. `SEGV` only is triggered if the pointer points inside a memory segment that is not accessible, but segments being several kBs in size, thus if you allocate 4 bytes at`10`, changes are that mem address `20` , despite outside an allocated area, is still in the same segment as address `10`, hence while not allocated, you will nevertheless be able to access address `20` without a SEGV. – Michael Beer Jun 18 '20 at 12:39
  • That's why you always should set unused pointers to `NULL`, cause this value *is* guaranteed to cause a SEGV if you try to dereference it... It is not guaranteed for any other memory address. – Michael Beer Jun 18 '20 at 12:45
  • @Michael Beer: "there is no guarantee that an invalid memory access will cause a SEGV" - right, but the check is still valid. If there is no SEGV then you can access the memory. – Peter Jan 19 '21 at 19:32
  • 1
    The question was: 'Is there a way to check whether a pointer was allocated in C?' your code is not suitable to check that. Your code only checks if the OS/MMU does not inhibit you from accessing it - this need not mean that it was properly allocated... – Michael Beer Jan 19 '21 at 19:46
9

For a platform-specific solution, you may be interested in the Win32 function IsBadReadPtr (and others like it). This function will be able to (almost) predict whether you will get a segmentation fault when reading from a particular chunk of memory.

However, this does not protect you in the general case, because the operating system knows nothing of the C runtime heap manager, and if a caller passes in a buffer that isn't as large as you expect, then the rest of the heap block will continue to be readable from an OS perspective.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • @Greg - Sorry to say I am not much intrested in WIN32 functions .. if possible a well working dirty hack is also ok since there is NO standard C function – codingfreak Oct 16 '09 at 07:32
  • 2
    Okay, you didn't specify what platform you *are* interested in. Specifying the platform and compiler may get you a more specific answer. – Greg Hewgill Oct 16 '09 at 07:53
  • 2
    [IsBadXxxPtr should really be called CrashProgramRandomly](http://blogs.msdn.com/b/oldnewthing/archive/2006/09/27/773741.aspx). – Alexey Frunze Apr 13 '12 at 11:02
8

I always initialize pointers to null value. Therefore when I allocate memory it will change. When I check if memory's been allocated I do pointer != NULL. When I deallocate memory I also set pointer to null. I can't think of any way to tell if there was enough memory allocated.

This doesn't solve your problem, but you got to trust that if someone writes C programs then he is skilled enough to do it right.

Yelonek
  • 623
  • 1
  • 5
  • 9
7

I once used a dirty hack on my 64bit Solaris. In 64bit mode the heap starts at 0x1 0000 0000. By comparing the pointer I could determine if it was a pointer in the data or code segment p < (void*)0x100000000, a pointer in the heap p > (void*)0x100000000 or a pointer in a memory mapped region (intptr_t)p < 0 (mmap returns addresses from the top of the addressable area). This allowed in my program to hold allocated and memory mapped pointers in the same map, and have my map module free the correct pointers.

But this kind of trick is highly unportable and if your code relies on something like that, it is time to rethink the architecture of your code. You're probably doing something wrong.

Patrick Schlüter
  • 11,394
  • 1
  • 43
  • 48
5

I know this is an old question, but almost anything is possible in C. There are a few hackish solutions here already, but a valid way of determining if memory has been properly allocated is to use an oracle to take the place of malloc, calloc, realloc, and free. This is the same way testing frameworks (such as cmocka) can detect memory problems (seg faults, not freeing memory, etc.). You can maintain a list of memory addresses allocated as they are allocated and simply check this list when the user wants to use your function. I implemented something very similar for my own testing framework. Some example code:

typedef struct memory_ref {
    void       *ptr;
    int        bytes;
    memory_ref *next;
}

memory_ref *HEAD = NULL;

void *__wrap_malloc(size_t bytes) {
    if(HEAD == NULL) {
        HEAD = __real_malloc(sizeof(memory_ref));
    }

    void *tmpPtr = __real_malloc(bytes);

    memory_ref *previousRef = HEAD;
    memory_ref *currentRef = HEAD->next;
    while(current != NULL) {
        previousRef = currentRef;
        currentRef = currentRef->next;
    }

    memory_ref *newRef = (memory_ref *)__real_malloc(sizeof(memory_ref));
    *newRef = (memory_ref){
        .ptr   = tmpPtr,
        .bytes = bytes,
        .next  = NULL
    };

    previousRef->next = newRef;

    return tmpPtr;
}

You would have similar functions for calloc, realloc, and free, each wrapper prefixed with __wrap_. The real malloc is available through the use of __real_malloc (similar for the other functions you are wrapping). Whenever you want to check if memory is actually allocated, simply iterate over the linked memory_ref list and look for the memory address. If you find it and it's big enough, you know for certain the memory address won't crash your program; otherwise, return an error. In the header file your program uses, you would add these lines:

extern void *__real_malloc  (size_t);
extern void *__wrap_malloc  (size_t);
extern void *__real_realloc (size_t);
extern void *__wrap_realloc (size_t);
// Declare all the other functions that will be wrapped...

My needs were fairly simple so I implemented a very basic implementation, but you can imagine how this could be extended to have a better tracking system (e.g. create a struct that keeps track of the memory location in addition to the size). Then you simply compile the code with

gcc src_files -o dest_file -Wl,-wrap,malloc -Wl,-wrap,calloc -Wl,-wrap,realloc -Wl,-wrap,free

The disadvantage is the user has to compile their source code with the above directives; however, it's far from the worse I have seen. There is some overhead to allocating and freeing memory, but there is always some overhead when adding security.

c1moore
  • 1,827
  • 17
  • 27
4

No, in general there is no way to do this.

Furthermore, if your interface is just "pass a pointer to a buffer where I will put stuff", then the caller may choose not to allocate memory at all, and instead use a fixed size buffer that's statically allocated or an automatic variable or something. Or perhaps it's a pointer into a portion of a larger object on the heap.

If your interface specifically says "pass a pointer to allocated memory (because I'm going to deallocate it)", then you should expect that the caller will do so. Failure to do so isn't something you can reliably detect.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • While this in general is the best answer, and mostly correct, I would say: Given enough effort, you could implement your own custom loader to track all memory allocations - or use an existing tool like `valgrind` ;) – Michael Beer Jun 18 '20 at 12:59
3

One hack you can try is checking if your pointer points to stack allocated memory. This will not help you in general as the allocated buffer might be to small or the pointer points to some global memory section (.bss, .const, ...).

To perform this hack, you first store the address of the first variable in main(). Later, you can compare this address with the address of a local variable in your specific routine. All addresses between both addresses are located on the stack.

swegi
  • 4,046
  • 1
  • 26
  • 45
  • Yeah ... If I write the whole application I can do that .. But inorder to use a function to check things might be complex ..? – codingfreak Oct 16 '09 at 08:27
  • This has the potential to cause someone to think that uninitialized pointers are on the heap. Also, if someone happened to store a pointer to somewhere farther down (up?) the stack, which later got popped off to get your function, it would also be considered on the heap. – Kevin Nov 11 '14 at 16:25
  • Distinguishing pointers in terms of having been allocated on the heap or stack does not really help here - what about `char copy[255] = {0}; snprintf(copy, sizeof(copy), "%n: %s\n", error_code, error_msg); copy[sizeof(copy) -1] = 0; write(log_fd, copy, strnlen(copy) + 1); copy[0] = 0;` if `snprintf` would perform weird checks like you suggested, `snprintf` would errorneously consider `copy` to be an invalid pointer... – Michael Beer Jun 18 '20 at 13:04
3

Well, I don't know if somebody didn't put it here already or if it will be a possibility in your programme. I was struggling with similar thing in my university project.

I solved it quite simply - In initialization part of main() , after I declared LIST *ptr, I just put that ptr=NULL. Like this -

int main(int argc, char **argv) {

LIST *ptr;
ptr=NULL;

So when allocation fails or your pointer isn't allocated at all, it will be NULL. SO you can simply test it with if.

if (ptr==NULL) {
  "THE LIST DOESN'T EXIST" 
} else {
  "THE LIST MUST EXIST --> SO IT HAS BEEN ALLOCATED"
}

I don't know how your programme is written, but you surely understand what am I trying to point out. If it is possible to check like this your allocation and then pass your arguments to you function, you could have a simple solution.

Of course you must be careful to have your functions with allocating and creating the structure done well but where in C you don't have to be careful.

OMGtechy
  • 7,935
  • 8
  • 48
  • 83
Patrick J
  • 41
  • 2
2

I don't know a way of doing it from a library call, but on Linux, you can look at /proc/<pid>/numa_maps. It will show all sections of memory and the third column will say "heap" or "stack". You can look at the raw pointer value to see where it lines up.

Example:

00400000 prefer:0 file=/usr/bin/bash mapped=163 mapmax=9 N0=3 N1=160
006dc000 prefer:0 file=/usr/bin/bash anon=1 dirty=1 N0=1
006dd000 prefer:0 file=/usr/bin/bash anon=9 dirty=9 N0=3 N1=6
006e6000 prefer:0 anon=6 dirty=6 N0=2 N1=4
01167000 prefer:0 heap anon=122 dirty=122 N0=25 N1=97
7f39904d2000 prefer:0 anon=1 dirty=1 N0=1
7f39904d3000 prefer:0 file=/usr/lib64/ld-2.17.so anon=1 dirty=1 N0=1
7f39904d4000 prefer:0 file=/usr/lib64/ld-2.17.so anon=1 dirty=1 N1=1
7f39904d5000 prefer:0 anon=1 dirty=1 N0=1
7fffc2d6a000 prefer:0 stack anon=6 dirty=6 N0=3 N1=3
7fffc2dfe000 prefer:0

So pointers that are above 0x01167000 but below 0x7f39904d2000 are located in the heap.

Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
1

There is a simple way to do this. Whenever you create a pointer, write a wrapper around it. For example, if your programmer uses your library to create a structure.

struct struct_type struct_var;

make sure he allocates memory using your function such as

struct struct_type struct_var = init_struct_type()

if this struct_var contains memory that is dynamically allocated, for ex,

if the definition of struct_type was

typedef struct struct_type {
 char *string;
}struct_type;

then in your init_struct_type() function, do this,

init_struct_type()
{ 
 struct struct_type *temp = (struct struct_type*)malloc(sizeof(struct_type));
 temp->string = NULL;
 return temp;
}

This way,unless he allocates the temp->string to a value, it will remain NULL. You can check in the functions that use this structure, if the string is NULL or not.

One more thing, if the programmer is so bad, that he fails to use your functions, but rather directly accesses unallocated the memory, he doesn't deserve to use your library. Just ensure that your documentation specifies everything.

wlan0
  • 190
  • 1
  • 11
1

You can't check with anything available in standard C. Even if your specific compiler were to provide a function to do so, it would still be a bad idea. Here's an example of why:

int YourFunc(char * buf, int buf_size);

char str[COUNT];
result = YourFunc(str, COUNT);
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • @Mark - In the code you are assigning str as an array of size COUNT .. hence in 'YourFunc' I can still perform operations like strcpy within the size of buf_size. But if str is just a char pointer then trying to perform any strcpy operation of size buf_size will result in a 'Segmentation Fault' – codingfreak Oct 16 '09 at 05:58
  • 2
    That's VERY VERY wrong, codingfreak. The segmentation fault happens if 'str' is a char pointer pointing at memory you're not allowed to access. It doesn't happen because 'str' is a char pointer, it happens because you ask the program to do something it's not allowed to do. – gnud Oct 16 '09 at 16:12
1

As everyone else said, there isn't a standard way to do it.

So far, no-one else has mentioned 'Writing Solid Code' by Steve Maguire. Although castigated in some quarters, the book has chapters on the subject of memory management, and discusses how, with care and complete control over all memory allocation in the program, you can do as you ask and determine whether a pointer you are given is a valid pointer to dynamically allocated memory. However, if you plan to use third party libraries, you will find that few of them allow you to change the memory allocation routines to your own, which greatly complicates such analysis.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • @Jonathan - What you mean by third party libraries -- ?? I am just using standard libraries and ISO C99. But I will just try out the book which you have recommended. – codingfreak Oct 16 '09 at 07:38
  • Third party libraries are anything you didn't write, including the standard libraries. Roughly speaking, if it uses malloc() anywhere, you will have a tough time replacing those calls with your own memory allocator, which means it will be hard to track abuses. You may have to go for more sophisticated memory tracking stuff - check out debugging versions of malloc, valgrind, Purify, etc. (It is the bane of my life - we can't use most libraries from outside without hard work because the product I work on has excruciating memory management requirements that libraries neither know nor care about.) – Jonathan Leffler Oct 16 '09 at 08:42
1

in general lib users are responsible for input check and verification. You may see ASSERT or something in the lib code and they are used only for debug perpose. it is a standard way when writing C/C++. while so many coders like to do such check and verfying in their lib code very carefully. really "BAD" habits. As stated in IOP/IOD, lib interfaces should be the contracts and make clear what will the lib do and what will not, and what a lib user should do and what should be not necessary.

Test
  • 1,697
  • 1
  • 11
  • 10
0

No, you can't. You'll notice that no functions in the standard library or anywhere else do this. That's because there's no standard way to tell. The calling code just has to accept responsibility for correctly managing the memory.

Chuck
  • 234,037
  • 30
  • 302
  • 389
0

An uninitialised pointer is exactly that - uninitialised. It may point to anything or simply be an invalid address (i.e. one not mapped to physical or virtual memory).

A practical solution is to have a validity signature in the objects pointed to. Create a malloc() wrapper that allocates the requested block size plus the sizeof a signature structure, creates a signature structure at the start of the block but returns the pointer to the location after the signature. You can then create a validation function that takes the pointer, uses a negative offset to get the validity structure and checks it. You will of course need a corresponding free() wrapper to invalidate the block by overwriting the validity signature, and to perform the free from the true start of the allocated block.

As a validity structure, you might use the size of the block and its one's complement. That way you not only have a way of validating the block (XOR the two values and compare to zero), but you also have information about the block size.

Clifford
  • 88,407
  • 13
  • 85
  • 165
0

A pointer tracker, tracks and checks the validity of a pointer

usage:

create memory int * ptr = malloc(sizeof(int) * 10);

add the pointer address to the tracker Ptr(&ptr);

check for failing pointers PtrCheck();

and free all trackers at the end of your code

PtrFree();

 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdbool.h>

struct my_ptr_t { void ** ptr; size_t mem; struct my_ptr_t *next, *previous; };

static struct my_ptr_t * ptr = NULL;

void Ptr(void * p){ 
                struct my_ptr_t * tmp = (struct my_ptr_t*) malloc(sizeof(struct my_ptr_t));
                printf("\t\tcreating Ptr tracker:");    
                if(ptr){ ptr->next = tmp; }
                tmp->previous = ptr;
                ptr = tmp;
                ptr->ptr = p;
                ptr->mem = **(size_t**) ptr->ptr;
                ptr->next = NULL;
                printf("%I64x\n", ptr); 
};
void PtrFree(void){
                    if(!ptr){ return; }
                    /* if ptr->previous == NULL */
                    if(!ptr->previous){ 
                                    if(*ptr->ptr){
                                                free(ptr->ptr);
                                                ptr->ptr = NULL;
                                    }
                                    free(ptr);
                                    ptr = NULL; 
                            return;                 
                    }

                    struct my_ptr_t * tmp = ptr;    
                    for(;tmp != NULL; tmp = tmp->previous ){
                                            if(*tmp->ptr){
                                                        if(**(size_t**)tmp->ptr == tmp->mem){
                                                                                                                                                    free(*tmp->ptr);
                                                                        *tmp->ptr = NULL;
                                                        }
                                            }
                                        free(tmp);
                    } 
            return; 
};

void PtrCheck(void){
                if(!ptr){ return; }
                if(!ptr->previous){
                        if(*(size_t*)ptr->ptr){
                                    if(*ptr->ptr){
                                                if(**(size_t**) ptr->ptr != ptr->mem){
                                                                printf("\tpointer %I64x points not to a valid memory address", ptr->mem);
                                                                printf(" did you freed the memory and not NULL'ed the pointer or used arthmetric's on pointer %I64x?\n", *ptr->ptr);
                                                                return; 
                                                        }   
                                    }
                                    return;
                                }
                        return;
                }
                struct my_ptr_t * tmp = ptr;
                for(;tmp->previous != NULL; tmp = tmp->previous){   
                                if(*(size_t*)tmp->ptr){         
                                                   if(*tmp->ptr){
                                                            if(**(size_t**) tmp->ptr != tmp->mem){
                                                                        printf("\tpointer %I64x points not to a valid memory address", tmp->mem);
                                                                        printf(" did you freed the memory and not NULL'ed the pointer or used arthmetric's on pointer %I64x?\n", *tmp->ptr);                            continue;
                                                            } 
                                                    }
                                                    continue;
                                }

                } 
            return;
       };

 int main(void){
        printf("\n\n\t *************** Test ******************** \n\n");
        size_t i = 0;
        printf("\t *************** create tracker ********************\n");
        int * ptr = malloc(sizeof(int) * 10);
        Ptr(&ptr);
        printf("\t *************** check tracker ********************\n");
        PtrCheck();
        printf("\t *************** free pointer ********************\n");
        free(ptr);
        printf("\t *************** check tracker ********************\n");
        PtrCheck();
        printf("\t *************** set pointer NULL *******************\n");
        ptr = NULL;
        printf("\t *************** check tracker ********************\n");
                PtrCheck();
        printf("\t *************** free tracker ********************\n");
        PtrFree();
        printf("\n\n\t *************** single check done *********** \n\n");
        printf("\n\n\t *************** start multiple test *********** \n");
        int * ptrs[10];
        printf("\t *************** create trackers ********************\n");
        for(; i < 10; i++){
                        ptrs[i] = malloc(sizeof(int) * 10 * i);
                        Ptr(&ptrs[i]);
                 }
        printf("\t *************** check trackers ********************\n");
        PtrCheck();
        printf("\t *************** free pointers but set not NULL *****\n");
        for(i--; i > 0; i-- ){ free(ptrs[i]); }
        printf("\t *************** check trackers ********************\n");
        PtrCheck(); 
        printf("\t *************** set pointers NULL *****************\n");
        for(i=0; i < 10; i++){ ptrs[i] = NULL; }
        printf("\t *************** check trackers ********************\n");
        PtrCheck(); 
        printf("\t *************** free trackers ********************\n");
        PtrFree();
        printf("\tdone");
    return 0;
 }
Andre
  • 172
  • 2
  • 8
0

I'm not sure how fast msync is, but this is a linux only solution:

// Returns 1 if the ponter is mapped
int pointer_valid (void *p)
{
  size_t pg_size = sysconf (_SC_PAGESIZE);
  void *pg_start = (void *) ((((size_t)p) / pg_size) * pg_size);
  return msync (pg_start, pg_size, MS_ASYNC) == 0;
}
Goblinhack
  • 2,859
  • 1
  • 26
  • 26
-2

There is almost never "never" in computers. Cross platform is way over anticipated. After 25 years I have worked on hundreds of projects all anticipating cross platform and it never materialized.

Obviously, a variable on the stack, would point to an area on the stack, which is almost linear. Cross platform garbage collectors work, by marking the top or (bottom) of the stack, calling a little function to check if the stack grows upwards or downwards and then checking the stack pointer to know how big the stack is. This is your range. I don't know a machine that doesn't implement a stack this way (either growing up or down.)

You simply check if the address of our object or pointer sits between the top and bottom of the stack. This is how you would know if it is a stack variable.

Too simple. Hey, is it correct c++? No. Is correct important? In 25 years I have seen way more estimation of correct. Well, let's put it this way: If you are hacking, you aren't doing real programming, you are probably just regurigating something that's already been done.

How interesting is that?

Jordan
  • 453
  • 4
  • 6
  • 1
    The original question was about C, not C++, didn't mention nor imply on-stack variables and wasn't about interesting/new/unique stuff. – Alexey Frunze Apr 13 '12 at 11:00
  • Besides, `malloc`-alike functions does not necessarily perform an action that will end up in heap expansion. C++ has a whole new different way of allocating memory and everyone knows that using the pre-defined functions of C is not a good idea. – Imobilis Aug 03 '16 at 08:31
  • Just knowing that you're passed a pointer that points into the stack somewhere is not useful. You still have to solve OP's problem, which is knowing how big the pointed-to buffer is. – melpomene Nov 17 '18 at 20:48