如何具体分配一大块堆内存中的各个部分如何指针转化为地址如何求指针间地址偏移量(谈谈最近遇到的一个坑爹的接口需求)

Posted NONE

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何具体分配一大块堆内存中的各个部分如何指针转化为地址如何求指针间地址偏移量(谈谈最近遇到的一个坑爹的接口需求)相关的知识,希望对你有一定的参考价值。

最近遇到一个坑爹的接口需求

其需求简单讲,就是要我传递一个头结构体USERCERTTABLE,一个用户(USER)结构体数组,一个证书(CERT)结构体数组……

 

讲道理,这样写就好了嘛Write_User_Cert(struct* head p1,struct* user p2. struct* cert p3);

不就是传递三个指针嘛

 

但是人家要求,参数只传递一个头结构体,然后在头结构体里写用户结构体数组的偏移量,和证书结构体数组的偏移量,然后接口只传USERCERTTABLE一个结构体作为参数,再通过偏移量求后面两个结构体数组

技术分享图片

我一开始想得是先new USERCERTTABLE结构体,再按顺序new USER结构体数组,再按顺序new CERT结构体数组

可得三个指针,p_user_cert_table,p_users,p_certs

之后DWORD user_cert_table_addr = (DWORD)p_user_cert_table

DWORD users_addr = (DWORD)p_users

DWORD certs_addr = (DWORD)p_certs

将指针强转求地址

然后偏移量就用地址相减就可以了

 

然后这样写忽略了一件事,那就是C++ 在堆内存开辟空间并不一定是顺序的,而DWORD又是无符号型数字,所以求得的偏移量如果数负数的话,存在DWORD里就变成正数了,这样一来偏移量就求反了

 

另外还有一个问题,32位下用DWORD类型求地址还行,64位下就不够了(4字节),会丢失精度,vs下用size_t类型即可

 

所以该怎么办呢?

按照接口的要求,其实我要做的是,开辟一大块对内存空间,再在其中对三块做具体分配,这样一来三者的排列是紧致的,不会有空余,也不会出现负数的偏移量

 

    int total_len = sizeof(USERCERTTABLE) + sizeof(USER)*user_num + sizeof(CERT)* cert_num;  //求总长度

    void *p1 = malloc(total_len);                                                        //开辟总的堆空间
    void *p2 = (USERCERTTABLE)p1 + 1;                                                    //p2指向用户结构体数组
    void *p3 = (USER)p2 + user_num;                                                      //p3指向证书结构体数组
    p_usercert_table = new (p1)USERCERTTABLE;                                            //p1开辟USERCERTTABLE空间
    p_user = new (p2)USER;                                                               //p2开辟USER数组空间
    p_cert = new (p3)CERT;                                                               //p3开辟CERT数组空间

 

必须这样写才行

也让我感叹C++的强大,可以如此灵活地操作内存

关键是,这样写有个J8意义啊,为什么不直接传三个指针呢?为了让内存排列紧密没空余吗?有什么意义?怎么不多考虑下开发的简易性和接口的易理解性呢?

为了验证自己调用接口传参的正确性,把这块内存写在文件里,一个字节一个字节去比对,真tm恶心。

以上是关于如何具体分配一大块堆内存中的各个部分如何指针转化为地址如何求指针间地址偏移量(谈谈最近遇到的一个坑爹的接口需求)的主要内容,如果未能解决你的问题,请参考以下文章

处理内存池中的碎片?

编译为 Wasm 时,指向堆分配内存的 Rust 指针可以为 0 吗?

内存映射:小块内存申请brk和申请大块内存的Mmap分析

如何使用 Next.js 为 Javascript 堆分配更多内存

C 语言二级指针作为输入 ( 自定义二级指针内存 | 为 二级指针 分配内存 - 存放 一维指针 | 为每个 一级指针 分配内存 | 释放二维指针内存 )

如何查看java虚拟机堆内存的参数值