主题
检测一个指针是否合法
注意: 这里只是检测一个指针是否可以访问, 不报错.
即对应地址在虚拟地址空间中, 有对应的页与物理地址对应;
并不能说明其已经被malloc了。
核心
参考链接
https://renatocunha.com/2015/12/msync-pointer-validity/
https://man7.org/linux/man-pages/man3/msync.3p.html
linux api
#include <sys/mman.h>
int msync(void *addr, size_t len, int flags);
说明
以addr
为起始地址, 长度为len
的内存数据, 按照flags
的方式同步到永久存储介质中(一般是磁盘);
成功返回0
, 失败返回-1 + errno
;
缓存到磁盘的同步
将cpu cache
刷新到存储介质中: cpu cache ==> memory ==> disk
; cache
的刷新会强制执行mesi
, 将其他core
的内容invalidate
; 这一步可选;
内存类型
一般是map_public
类型, 不过这里检测可以用于map_private
类型; 可能不会写入存储介质; 这里也仅仅是检查debug
的手段;
案例
核心代码
#include <sys/mman.h>
#include <stdbool.h>
#include <unistd.h>
bool is_pointer_valid(void *p) {
/* get the page size */
size_t page_size = sysconf(_SC_PAGESIZE);
/* find the address of the page that contains p */
void *base = (void *)((((size_t)p) / page_size) * page_size);
/* call msync, if it returns non-zero, return false */
return msync(base, page_size, MS_ASYNC) == 0;
}
候选返回值判断
int ret = msync(base, page_size, MS_ASYNC) != -1;
return ret ? ret : errno != ENOMEM;
完整案例
#include <sys/mman.h>
#include <stdbool.h>
#include <unistd.h>
bool is_pointer_valid(void *p) {
/* get the page size */
size_t page_size = sysconf(_SC_PAGESIZE);
/* find the address of the page that contains p */
void *base = (void *)((((size_t)p) / page_size) * page_size);
/* call msync, if it returns non-zero, return false */
return msync(base, page_size, MS_ASYNC) == 0;
}
#include <stdio.h>
int main() {
void* null = reinterpret_cast<void*>(0x05050505);
auto ret = is_pointer_valid(null);
printf("addr = %p, valid : %s \n", null, ret ? "True" : "False");
null = reinterpret_cast<void*>(&main);
ret = is_pointer_valid(null);
printf("addr = %p, valid : %s \n", null, ret ? "True" : "False");
return 0;
}
执行输出
$ ./a.out
addr = 0x5050505, valid : False
addr = 0x558a70489729, valid : True
文章评论