我的意思是给 struct\memory 中的变量指针,然后给它一些函数,它会给我指向 struct\memory 开头的指针。有一个功能可以做到吗?
要理解这个问题:
char* ptr=((char*)malloc(12))+3;
//MemStart(ptr) == ptr-3
MemStart
'将是在代码中给出该结果的函数。
我的意思是给 struct\memory 中的变量指针,然后给它一些函数,它会给我指向 struct\memory 开头的指针。有一个功能可以做到吗?
要理解这个问题:
char* ptr=((char*)malloc(12))+3;
//MemStart(ptr) == ptr-3
MemStart
'将是在代码中给出该结果的函数。
除非该结构在内存中的表示存在特定的内容(例如它始终以字节 0xff、0xff 开头),否则无法确定特定结构或数组的开始位置。现代架构是冯诺依曼机器,这意味着内存没有内在意义。
请注意,许多架构都存在对齐问题或优化,这意味着结构或数组可能需要从 16 位、32 位或 64 位字边界开始,但这些是特定于架构的。
[编辑:添加以下内容]
库可能会在分配的内存块的开头或结尾引入保护字节,或者用已知常量填充内存以查找缓冲区溢出或错误指针。但是,这些通常在发布模式中被忽略,即使它们存在,也可能是有效数据。
您可以检查内存分配表以获取动态分配的内存,但可以在堆栈而不是堆上分配数组/结构。另外,如果数组中有一个结构会发生什么?它返回哪个值?如果您想将其限制为仅动态分配的内存,您希望仅在其中开始分配任何内存,Basile 有一个很好的答案。
大多数malloc
实现都没有提供您想要的(动态分配块的起始地址,给定一些指向它的内部指针)。标准不需要这样的东西。因此,您可能希望同时使用指向基址的指针和偏移量(也许将它们打包在一些 C++class fat_pointer
中operator*
并operator->
给出指针的错觉等)。
您当然可以重新实现您自己的malloc
上述操作系统内存段分配(即Linux 或 Posix 上的mmap(2)munmap(2)
)和解除分配原语系统调用。
您还可以拥有专门的分配器;它可能会使用posix_memalign为您的区域分配大的二次方对齐(例如 256 或 4096 字节) ,然后对intptr_t
指针的转换使用位操作。
请注意,实现任何重要的内存分配器都意味着关心操作系统和体系结构的不可移植的细节(对齐,...)。
您还可以使用Boehm 的保守垃圾收集器,即使用GC_malloc
而不是malloc
(并且不要打扰GC_free
您的动态数据);那么你就有了GC_base
完全符合你要求的功能:
/* 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);
您可以使用以下offsetof()
宏<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;
}
输出(ideone):
address of s:0xbffd266c
address of s.a:0xbffd266c
address of s.b:0xbffd2670
ps:0xbffd266c