在linux系统下使用内存技术,检测堆越界错误
越界监测技术1
一般使用c或cpp编程时,堆栈越界访问(read/write)往往会引起很多意想不到的错误,比如延后的进程崩溃等。因此,如果有一种方法,可以让越界访问立即触发系统错误(让进程抛出异常而终止,再生成coredump文件),就可以立即检测出内存越界行为,并将对这种隐藏的错误,及时作出反应,以免在生产环境下造成更大的损失。
我们知道,在windows系统下面,我们可以使用VirtualAlloc系列函数,通过申请2页内存,并设置某页的保护参数(比如,可读,可写等),就可以实现类似的保护机制。这样,当我们对新增加的类(数据结构),就可以重载operator new/delete,将类的边界设置到一页的边缘,再将相邻页设置为不可读不可写。这样就能有效监测堆越界读写问题。而且可以,设置某个编译宏,比如PROTECT_CLASSX。演示代码如下:#define ONE_PAGE_SIZE (1024*4) class NewClassX { public: const static size_t One_Page = ONE_PAGE_SIZE; static void * operator new (size_t size) { void * pOrigin = VirtualAlloc(nullptr, One_Page * 2, MEM_RESERVE, PAGE_READWRITE); if(pOrigin == nullptr) return nullptr; void * p = VirtualAlloc((BYTE*)pOrigin+One_Page, One_Page, MEM_RESERVE, PAGE_NOACCESS); return (BYTE*)p - size; } static void operator delete(void * p) { NewClassX * obj = (NewClassX*)p; obj->~NewClassX(); void * pOrigin = (BYTE*)p - (One_Page - sizeof(NewClassX)); VirtualFree(pOrigin); } //... other operations private: // private states; }
在linux下,则需要借助mmap和mprotect来实现这个机制。具体步骤如下,首先用mmap使用PROT_NONE映射一个特殊文件,比如/dev/zero(或者使用MAP_ANONYMOUS),然后再用mprotect提交内存。上面的例子,可以继续使用,但是只列出来核心的代码,什么重载操作符就不写了,另外,内存映射文件j句柄最好用内存池来hold,最后在close掉。演示代码只说明大致用法,并不能直接拿来用。void * VirtualAllocInLinux(int fd, size_t size) { void * pMmstart = mmap(nullptr, 2* One_Page, PROT_READ|PROT_WRITE, fd, 0); void * p = mprotect((BYTE*)pMmstart+One_Page, One_Page, PROT_NONE); return (BYTE*)pMmstart + One_Page - size; } void VirtualFreeInLinux(void * p) { NewClassX * obj = (NewClassX*)p; obj->~NewClassX(); void * pOrigin = (BYTE*)p + sizeof(NewClassX) - One_Page; munmap(pOrigin, 2 * One_Page); }
下面补充mprotect的用法:#include #include #include #include #include #include #include #define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) char *buffer; static void handler(int sig, siginfo_t *si, void *unused) { printf("Got SIGSEGV at address: 0x%lx ", (long) si->si_addr); exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { char *p; int pagesize; struct sigaction sa; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = handler; if (sigaction(SIGSEGV, &sa, NULL) == -1) handle_error("sigaction"); pagesize = sysconf(_SC_PAGE_SIZE); if (pagesize == -1) handle_error("sysconf"); /* Allocate a buffer aligned on a page boundary; initial protection is PROT_READ | PROT_WRITE */ buffer = memalign(pagesize, 4 * pagesize); if (buffer == NULL) handle_error("memalign"); printf("Start of region: 0x%lx ", (long) buffer); if (mprotect(buffer + pagesize * 2, pagesize, PROT_READ) == -1) handle_error("mprotect"); for (p = buffer ; ; ) *(p++) = "a"; printf("Loop completed "); /* Should never happen */ exit(EXIT_SUCCESS); }
再把mmap函数的用法示例如下:#include #include #include #include #include #include #define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) int main(int argc, char *argv[]) { char *addr; int fd; struct stat sb; off_t offset, pa_offset; size_t length; ssize_t s; if (argc < 3 || argc > 4) { fprintf(stderr, "%s file offset [length] ", argv[0]); exit(EXIT_FAILURE); } fd = open(argv[1], O_RDONLY); if (fd == -1) handle_error("open"); if (fstat(fd, &sb) == -1) /* To obtain file size */ handle_error("fstat"); offset = atoi(argv[2]); pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1); /* offset for mmap() must be page aligned */ if (offset >= sb.st_size) { fprintf(stderr, "offset is past end of file "); exit(EXIT_FAILURE); } if (argc == 4) { length = atoi(argv[3]); if (offset + length > sb.st_size) length = sb.st_size - offset; /* Canaqt display bytes past end of file */ } else { /* No length arg ==> display to end of file */ length = sb.st_size - offset; } addr = mmap(NULL, length + offset - pa_offset, PROT_READ, MAP_PRIVATE, fd, pa_offset); if (addr == MAP_FAILED) handle_error("mmap"); s = write(STDOUT_FILENO, addr + offset - pa_offset, length); if (s != length) { if (s == -1) handle_error("write"); fprintf(stderr, "partial write"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
三星NOTE7爆炸疑云未定,有用户称华为P9爆炸,被当场打脸今日,一条三星KOL发的一条微博引起轩然大波,该微博称今年4月份发布的P9发生爆炸,并附上三组图片。小编看到这个微博的第一反应就是三星开始洗地反攻了。不少三星粉丝在此微博下拍手称赞
华为双摄像头手机的大光圈到底该怎么用?在相机上,一般拍人像都是用定焦镜头,比如佳能的小痰盂50定。为什么用定焦,因为大光圈。大光圈镜头是拍人像的最好的镜头,因为大光圈下拍出来的照片能使主题更加突出,除主题外的都虚化了,
荣耀手表S1现代科技与传统美学的完美融合最近比较关注智能穿戴,有没有一款像传统手表样式的智能手表,如去年的荣耀zero,北欧简约风格,加之非常合适的价格当时就毫不犹豫的入手了。但是随着智能穿戴的设备发展,智能手表的功能越
华为荣耀引擎耳机2会旋转的耳机,这才是黑科技在100元这个价位上,琳琅满目的耳机,大都是普通至极,没什么能吸引我的地方。其实说白了主要是穷,现在买手机都不送耳机了,在这里强烈鄙视下各大手机厂商。不过呢,最近被一款可以物理调音
华为荣耀Magic评测,智慧手机是噱头还是黑科技?16年12月16日下午,华为荣耀Magic发布,官方宣称Magic是一款拥有智慧的手机。本人有幸参加了这次发布会,印象中最深刻的便是荣耀总裁赵明在介绍这款手机时的激情四射,而且我还
扫盲华为mate9上的专业模式你会用吗?华为手机的拍照pro,也就是所谓的专业模式。专业模式由来单反相机。很多华为永华对专业模式望而却步,其实掌握了这几点,什么专业模式都是小菜一叠。以华为mate9为例,打开方式,上划相
林肯之道2。0跨平台数据共享实现智享便捷随着美式豪华的与时俱进,拥有百年荣耀的林肯,正逐渐吸引更多年轻客户的青睐,在中国市场稳步前行。林肯认为与时俱进的美式豪华不止于优质的驾乘体验,更在于尊贵温暖的服务。林肯之道是林肯对
领跑国货之光,索爱在社交平台收获数千万阅读量近日,索爱广州25周年庆领跑活动在网络持续发酵,引爆舆论热烈关注。作为音频数码行业首个登录广州塔的国货品牌,索爱25周年领跑活动吸引了大量的媒体和达人齐聚广州塔,索爱品牌和产品热度
自动驾驶,退一步海阔天空中国能诞生自动驾驶领域的博世吗?文东篱对于自动驾驶,太多人瞄准那块万亿美元规模的出行蛋糕。但如果从ADAS出发,一步一步走向L4甚至L5,在Robotaxi时代降临前,更深入参与汽
传统车企为什么敌不过特斯拉?华尔街的资本和硅谷的科技创新位于微笑曲线的两头,很多车企沉溺在曲线的底部,在制造中忙碌。文Toretto当我们对特斯拉自造电池习以为常,之于汽车行业,这真是一件可怕的事情。几乎所有
车企的出行迷局若不愿冒险,就只能倒在起点。文Toretto车企不能再像过去那样卖车了。当不同赛道各个行业的对手涌入战场,汽车巨头们一旦停步就意味着被淘汰,或者沦为领跑者的附庸。在逐渐成为行业共识