当前位置: 首页 > news >正文

网站建设类电话销售啥都有是什么购物平台

网站建设类电话销售,啥都有是什么购物平台,logo123设计网,视频网站直播怎么做C进阶专栏#xff1a;http://t.csdnimg.cn/aTncz 相关系列文章 C技术要点总结, 面试必备, 收藏起来慢慢看 C惯用法之RAII思想: 资源管理 C智能指针的自定义销毁器(销毁策略) 目录 1.内存泄漏概述 1.1.内存泄漏产生原因 1.2 内存泄漏导致的后果 1.3 内存泄漏解决思路 2.宏… C进阶专栏http://t.csdnimg.cn/aTncz 相关系列文章 C技术要点总结, 面试必备, 收藏起来慢慢看 C惯用法之RAII思想: 资源管理 C智能指针的自定义销毁器(销毁策略) 目录 1.内存泄漏概述 1.1.内存泄漏产生原因 1.2 内存泄漏导致的后果 1.3 内存泄漏解决思路 2.宏定义方法 2.1.宏定义 2.2.检测位置 2.3.结果分析 3.hook方法 3.1.hook 3.2.检测位置 3.3 递归调用 3.4.结果分析 3.5.addr2line 4.__libc_malloc 和 __libc_free 1.内存泄漏概述 1.1.内存泄漏产生原因 内存泄漏是在没有自动 gc 的编程语言里面经常发生的一个问题。 自动垃圾回收Automatic Garbage Collection简称 GC是一种内存管理技术在程序运行时自动检测和回收不再使用的内存对象以避免内存泄漏和释放已分配内存的负担。 因为没有 gc所以分配的内存需要程序员自己调用释放。其核心原因是调用分配与释放没有符合开闭原则没有配对形成了有分配没有释放的指针从而产生了内存泄漏。 void myTest(size_t s1) {void a1malloc(s1);void a2malloc(s1);free(a1); } 以上代码段分配了两个s1大小的内存块由 a1 与 a2 指向。而代码块执行完以后释放了 a1而 a2 没有释放。形成了有分配没有释放的指针产生了内存泄漏。 1.2 内存泄漏导致的后果 随着工程代码量越来越多有分配没有释放自然会使得进程堆的内存会越来越少直到耗尽。从而导致后面的运行时代码不能成功分配内存使程序崩溃。 1.3 内存泄漏解决思路 最好的办法肯定是引入自动垃圾回收gc。但是这不适合C/C语言。 解决内存泄漏我们需要解决两点 1能够检测出来是否发送内存泄漏 2如果发生内存泄漏能够检测出来具体是哪一行代码所引起的。 内存泄漏是由于内存分配与内存释放不匹配所引起的。因此对内存分配函数malloc/calloc/realloc以及内存释放函数free进行“劫持”hook就能能够统计出内存分配的位置内存释放的位置从而判断是否匹配。 2.宏定义方法 2.1.宏定义 使用宏定义替换系统的内存分配接口。并利用__FILE__、__LINE__分别获取当前编译文件的文件名、行号进行追踪位置信息。 #define malloc(size) _malloc(size, __FILE__, __LINE__) #define free(ptr) _free(ptr, __FILE__, __LINE__) 需要注意的是宏定义一定要放在内存分配之前这样预编译阶段才会替换为我们自己实现的_malloc和_free。 2.2.检测位置 为了方便观察我们可以在内存分配_malloc的时候创建一个文件。文件名为指向新分配内存的指针值文件内容为指针值、调用_malloc时的文件名、行号。 在该内存释放_free的时候删除该指针对应的文件。 最后程序运行结束如果没有文件说明没有内存泄漏否则说明存在内存泄漏。 2.3.结果分析 #include stdio.h #include stdlib.h #include unistd.hvoid *_malloc(size_t size, const char *filename, int line){void *ptr malloc(size);char buffer[128] {0};sprintf(buffer, ./memory/%p.memory, ptr);FILE *fp fopen(buffer, w);fprintf(fp, []addr: %p, filename: %s, line: %d\n, ptr, filename, line);fflush(fp);fclose(fp);return ptr; }void _free(void *ptr, const char *filename, int line){char buffer[128] {0};sprintf(buffer, ./memory/%p.memory, ptr);if (unlink(buffer) 0){printf(double free: %p\n, ptr);return;}return free(ptr); }#define malloc(size) _malloc(size, __FILE__, __LINE__) #define free(ptr) _free(ptr, __FILE__, __LINE__)int main() {void *p1 malloc(5);void *p2 malloc(18);void *p3 malloc(15);free(p1);free(p3); } 最后在memory文件夹里可以看到存在一个文件说明有一个地方出现内存泄漏 []addr: 0x559e55b6e8b0, filename: fun1.c, line: 39 从结果上看内存泄漏发生第39行。 3.hook方法 利用 hook 机制改写系统的内存分配函数。 3.1.hook hook方法的实现分三个步骤 1定义函数指针。 typedef void *(*malloc_t)(size_t size); malloc_t malloc_f NULL;typedef void (*free_t)(void *ptr); free_t free_f NULL; 2函数实现函数名与目标函数名一致。 void *malloc(size_t size) {//改写的功能 }void free(void *ptr) {//改写的功能 } 3初始化hook调用dlsym()。 void init_hook(){if (!malloc_f){malloc_f dlsym(RTLD_NEXT, malloc);}if (!free_f){free_f dlsym(RTLD_NEXT, free);} } 3.2.检测位置 宏定义的方法在检测调用所在行号的时候使用了系统定义的__LINE__因为是宏定义的malloc预编译时候直接嵌入。因此__LINE__返回的就是调用malloc的位置。 但是hook方法不一样系统定义的__LINE__在函数内部调用无法确定在主函数中的调用位置。比如 fprintf(fp, []addr: %p, filename: %s, line: %d\n, ptr, filename, line); 返回的就是fprintf所在的行号。 因此使用gcc 提供的__builtin_return_address该函数返回当前函数或其调用者之一的返回地址。参数level 表示向上扫描调用堆栈的帧数。比如对于 main -- f1() -- f2() -- f3() f3()函数里面调用 __builtin_return_address (0)返回f3的地址调用 __builtin_return_address (1)返回f2的地址 3.3 递归调用 hook的时候要考虑其他函数也用到所hook住的函数比如在printf()函数里面也调用了malloc那么就需要防止内部递归进入死循环。 通过gdb调试在第23行打断点发现每次运行都回到了23行。 这是因为sprintf隐含调用了malloc这样就陷入一个循环 23行的sprintf — 自定义的malloc — 23行的sprintf — 自定义的malloc -- 23行的sprintf — 自定义的malloc -- …… 解决办法是限制调用次数。当进入 malloc 函数内部后根据自己的需要设置 hook 的开关。在关闭的区域内调用 malloc 后进入到 else 部分执行原来的 hook 函数避免了无限递归的发生。 int enable_malloc_hook 1; void *malloc(size_t size) { // 执行改写的 malloc 函数if (enable_malloc_hook) {enable_malloc_hook 0;// 关闭 hook, printf 内部的 malloc 执行 else 的部分// 其他代码enable_malloc_hook 1;}// 执行原来的 malloc 函数else {p malloc_f(size);} } 3.4.结果分析 // gcc -o fun2 fun2.c -ldl -g#define _GNU_SOURCE #include dlfcn.h#include stdio.h #include stdlib.h #include unistd.h #include link.htypedef void *(*malloc_t)(size_t size); malloc_t malloc_f NULL;typedef void (*free_t)(void *ptr); free_t free_f NULL;int enable_malloc_hook 1; int enable_free_hook 1;void *malloc(size_t size){void *ptr NULL;if (enable_malloc_hook ){enable_malloc_hook 0; enable_free_hook 0;ptr malloc_f(size);void *caller __builtin_return_address(0);char buffer[128] {0};sprintf(buffer, ./memory/%p.memory, ptr);FILE *fp fopen(buffer, w);fprintf(fp, [] caller: %p, addr: %p, size: %ld\n, caller, ptr, size);fflush(fp);fclose(fp);enable_malloc_hook 1;enable_free_hook 1;}else {ptr malloc_f(size);}return ptr; }void free(void *ptr){if (enable_free_hook ){enable_free_hook 0;enable_malloc_hook 0;char buffer[128] {0};sprintf(buffer, ./memory/%p.memory, ptr);if (unlink(buffer) 0){printf(double free: %p\n, ptr);return;}free_f(ptr);enable_malloc_hook 1;enable_free_hook 1;}else {free_f(ptr);} }void init_hook(){if (!malloc_f){malloc_f dlsym(RTLD_NEXT, malloc);}if (!free_f){free_f dlsym(RTLD_NEXT, free);} } int main(){init_hook();void *p1 malloc(5);void *p2 malloc(18);void *p3 malloc(15);free(p1);free(p3); } 从结果看存在一个内存泄漏但是 caller0x16bb 是地址不是具体行号。使用addr2line可以将地址转换为文件名和行号。 3.5.addr2line 利用addr2line工具将地址转换为文件名和行号得到源文件的行数根据机器码地址定位到源码所在行数) addr2line -f -e fun2 -a 0x16bb 参数-f显示函数名信息。-e filename指定需要转换地址的可执行文件名。-a address显示指定地址十六进制。 但是高版本 gcc 下使用 addr2line 命令会出现乱码问题。 ?? ??:0 addr2line 作用于 ELF 可执行文件而高版本的 gcc 调用 __builtin_return_address返回的地址 caller 位于内存映像上所以会产生乱码。 解决办法是利用动态链接库的dladdr函数 作用于共享目标可以获取某个地址的符号信息。使用该函数可以解析符号地址。如下 // gcc -o fun2 fun2.c -ldl -g#define _GNU_SOURCE #include dlfcn.h#include stdio.h #include stdlib.h #include unistd.h #include link.h// 解析地址 void* converToELF(void *addr) {Dl_info info;struct link_map *link;dladdr1(addr, info, (void **)link, RTLD_DL_LINKMAP);// printf(%p\n, (void *)(size_t)addr - link-l_addr);return (void *)((size_t)addr - link-l_addr); }typedef void *(*malloc_t)(size_t size); malloc_t malloc_f NULL;typedef void (*free_t)(void *ptr); free_t free_f NULL;int enable_malloc_hook 1; int enable_free_hook 1;void *malloc(size_t size){void *ptr NULL;if (enable_malloc_hook ){enable_malloc_hook 0; ptr malloc_f(size);void *caller __builtin_return_address(0);char buffer[128] {0};sprintf(buffer, ./memory/%p.memory, ptr);FILE *fp fopen(buffer, w);// converToELF(caller)fprintf(fp, [] caller: %p, addr: %p, size: %ld\n, converToELF(caller), ptr, size);fflush(fp);fclose(fp);enable_malloc_hook 1;}else {ptr malloc_f(size);}return ptr; }void free(void *ptr){if (enable_free_hook ){enable_free_hook 0;char buffer[128] {0};sprintf(buffer, ./memory/%p.memory, ptr);if (unlink(buffer) 0){printf(double free: %p\n, ptr);return;}free_f(ptr);enable_free_hook 1;}else {free_f(ptr);} }void init_hook(){if (!malloc_f){malloc_f dlsym(RTLD_NEXT, malloc);}if (!free_f){free_f dlsym(RTLD_NEXT, free);} } int main(){init_hook();void *p1 malloc(5);void *p2 malloc(18);void *p3 malloc(15);free(p1);free(p3); } 4.__libc_malloc 和 __libc_free 思路和hook的一样因为malloc和free底层调用的也是__libc_malloc和__libc_free。 // gcc -o fun3 fun3.c #define _GNU_SOURCE #include dlfcn.h #include stdio.h #include stdlib.h #include unistd.h #include link.hvoid* converToELF(void *addr) {Dl_info info;struct link_map *link;dladdr1(addr, info, (void **)link, RTLD_DL_LINKMAP);// printf(%p\n, (void *)(size_t)addr - link-l_addr);return (void *)((size_t)addr - link-l_addr); }extern void *__libc_malloc(size_t size); extern void *__libc_free(void *ptr);int enable_malloc_hook 1; int enable_free_hook 1;void *malloc(size_t size){void *ptr NULL;if (enable_malloc_hook ){enable_malloc_hook 0; enable_free_hook 0;ptr __libc_malloc(size);void *caller __builtin_return_address(0);char buffer[128] {0};sprintf(buffer, ./memory/%p.memory, ptr);FILE *fp fopen(buffer, w);fprintf(fp, [] caller: %p, addr: %p, size: %ld\n, converToELF(caller), ptr, size);fflush(fp);fclose(fp);enable_malloc_hook 1;enable_free_hook 1;}else {ptr __libc_malloc(size);}return ptr; }void free(void *ptr){if (enable_free_hook ){enable_free_hook 0;enable_malloc_hook 0;char buffer[128] {0};sprintf(buffer, ./memory/%p.memory, ptr);if (unlink(buffer) 0){printf(double free: %p\n, ptr);return;}__libc_free(ptr);enable_malloc_hook 1;enable_free_hook 1;}else {__libc_free(ptr);} }int main(){void *p1 malloc(5);void *p2 malloc(18);void *p3 malloc(15);free(p1);free(p3); }
http://www.zqtcl.cn/news/915245/

相关文章:

  • 自贡网站开发河南省建设网站首页
  • 昆明网站推广优化服务器代理
  • wordpress 网站统计插件福建省建设工程职业注册网站
  • 手机移动端网站是什么上海网站设计服务商
  • 多语言网站建设推广孝感门户网
  • 外贸soho 网站建设旅游电子商务网站建设调查问卷
  • 北京专业制作网站seo优化技术教程
  • 网站建设最低多少钱珠海在线网站制作公司
  • 网站建设完成之后要索取哪些医疗网站建设服务
  • 长沙招聘网站有哪些深圳seo论坛
  • 网站如何做网络推广山西住房建设厅官方网站
  • 优化排名推广技术网站平面设计创意
  • 山西网站建设哪家有tv域名的网站
  • 个人博客网站怎么赚钱公司招聘一个网站建设来做推广
  • 功能型网站有哪些中国门户网站有哪些
  • 网站制作教程步骤软件公司怎么赚钱
  • 看世界杯网址网站更新seo
  • 深圳网站做的好的公司商洛做网站电话
  • 环保部网站官网建设项目审批做网站推广赚钱吗
  • 北仑建设局网站东莞市seo网络推广价格
  • 大专学历怎么自考优化建站
  • 网站上的图片怎么替换中国电力建设集团网站
  • 开发手机网站步骤手机网站前端开发布局技巧
  • 文山文山市网站建设网站建设管理教程视频
  • 深圳建筑业协会官网seo短视频新地址在哪里
  • 学院宣传网站制作大型网站团队人数
  • 新品发布会ppt参考友山建站优化
  • 做网站云服务器装系统厦门网站建设哪家强
  • 网站建设顶呱呱东莞建设信息网官网
  • 化妆品网站下载企业宣传片报价明细