Short answer: no. Long answer: definitely not :-)
There are tricks you can implement, such as the use of doubly-indirect pointers (an allocated structure that contains the pointer to the actual back-end data)(a), this is basically how smart pointers work in C++ and I've seen them implemented in C before(b). These are much more complex than raw pointers in that they may require mutex-protected reference counts, and all usage to only go through the API.
But the code manipulating these pointers may not necessarily be your code so, if you pass the back-end pointer through to some function that frees it without going through your API, all bets are off. In addition, it adds an extra level of indirection expense to every access.
(a) A simple example of this (no reference counting) is along the lines of:
pointerA +---------------+ +-------------+
>---> | smart pointer | -> | actual data |
pointerB +---------------+ +-------------+
All access is indirect via the smart pointer, which can be set to NULL when either of pointerA
or pointerB
is "freed". Hence, if you free pointerA
, then try to use pointerB
, the value you get will be NULL.
This requires an API for creating and destroying the smart pointers, getting and setting the back-end raw pointer, and so on.
(b) GObject, for example, is a partially reference-counted variant using smart pointers in C. It forms the basis of the object model in Gtk and GStreamer.
Early versions of Windows, long before protected mode when there was no memory management hardware (I'm revealing my age there !) used a similar double-indirect scheme so it could move memory around at will without all the processes ending up with invalid pointers.