Reputation: 429
I mean to give pointer to variable in struct\memory and then give it to some function and it'll give me pointer to the start of the struct\memory. There is a function that does it?
To understand this question:
char* ptr=((char*)malloc(12))+3;
//MemStart(ptr) == ptr-3
MemStart
'll be the function that'll give that result in the code.
Upvotes: 0
Views: 512
Reputation: 1
Most malloc
implementations don't provide what you want (the starting address of a dynamically allocated block, given some internal pointer to it). And the standards don't require anything like that. So you may want to use both pointer to base, and offset (perhaps packing them inside some C++ class fat_pointer
with operator*
and operator->
giving the illusion of pointers, etc, etc).
You could of course re-implement your own malloc
above operating system memory segment allocation (i.e. mmap(2) on Linux or Posix) and de-allocation munmap(2)
primitive syscalls.
You could also have your specialized allocator; it might allocate your zones with a large power-of-two alignment (e.g. 256 or 4096 bytes) using posix_memalign, then use bits manipulation on the intptr_t
cast of your pointer.
Notice that implementing any serious memory allocator means caring about unportable details of your operating system and architecture (alignment, ...).
You could also use Boehm's conservative garbage collector, that is use GC_malloc
instead of malloc
(and don't bother GC_free
-ing your dynamic data); then you have the GC_base
function which does exactly what you want:
/* Return a pointer to the base (lowest address) of an object given */
/* a pointer to a location within the object. */
/* I.e. map an interior pointer to the corresponding bas pointer. */
/* Note that with debugging allocation, this returns a pointer to the */
/* actual base of the object, i.e. the debug information, not to */
/* the base of the user object. */
/* Return 0 if displaced_pointer doesn't point to within a valid */
/* object. */
/* Note that a deallocated object in the garbage collected heap */
/* may be considered valid, even if it has been deallocated with */
/* GC_free. */
GC_API void * GC_base(void * displaced_pointer);
Upvotes: 2
Reputation: 14386
Unless there is something specific to that structure's representation in memory (such as it always starts with the bytes 0xff, 0xff), there is no way to determine where a particular structure or array starts. Modern architectures are Von Neuman machines, meaning memory has no inherent meaning.
Note that many architectures have alignment issues or optimizations, meaning structures or arrays may need to start on 16-bit, 32-bit or 64-bit word boundaries, but these are architecture specific.
[Edit: Added the following]
The library may introduce guard bytes at the start or end of the allocated block of memory or fill memory with known constants to look for buffer overflows or errant pointers. However, these are usually omitted in release mode and, even if they are present, may also be valid data.
You could inspect the memory allocation table for dynamically allocated memory but the array/struct could be allocated on the stack rather than the heap. Also, what happens if you have a structure within an array? Which value does it return? If you want to restrict it to just dynamically allocated memory where you want the start of whatever memory was allocated only, Basile has a great answer.
Upvotes: 3
Reputation: 62058
You can use the offsetof()
macro from <cstddef>
:
#include <cstddef>
#include <iostream>
using namespace std;
typedef struct
{
int a;
int b;
} S;
int main()
{
S s = { 1, 2 };
cout << "address of s:" << &s << endl;
cout << "address of s.a:" << &s.a << endl;
cout << "address of s.b:" << &s.b << endl;
int* pb = &s.b;
S* ps = (S*)((char*)pb - offsetof(S, b));
cout << "ps:" << ps << endl;
return 0;
}
Output (ideone):
address of s:0xbffd266c
address of s.a:0xbffd266c
address of s.b:0xbffd2670
ps:0xbffd266c
Upvotes: 0