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

佛山网站建设哪家公司好哪个网站做农产品

佛山网站建设哪家公司好,哪个网站做农产品,欧美网站建设,怎样做好网站建设前面介绍的mtrace也好,bcc也罢,其实都是hook技术的一种实现,但是mtrace本身使用场景上有局限,而bcc环境依赖则十分复杂。因此,这些调试手段只适用于开发环境用来调试,对于生产环境,均不是一个非…

前面介绍的mtrace也好,bcc也罢,其实都是hook技术的一种实现,但是mtrace本身使用场景上有局限,而bcc环境依赖则十分复杂。因此,这些调试手段只适用于开发环境用来调试,对于生产环境,均不是一个非常好的方法。

但其实所谓的hook技术,本身并不复杂,说白了就是重载malloc/free函数,让代码在调用malloc函数时,先调用我们自己定义的malloc,由自定义的malloc完成一些前置统计工作后,再去调用系统的malloc,从而完成一些内存的统计分析。明白了这一点,其实我们可以轻而易举地自己实现一套hook机制,嵌入到代码中,这样带来的好处显而易见:

  • 不依赖其他检测工具,可以非常方便地在开发环境甚至在线上进行调试
  • 可以在代码里通过开关的方式控制是否检测内存泄漏,如线上默认关闭,如果怀疑出现内存泄漏,则将开关打开,可以非常方便地定位问题
  • 系统无关,可以针对不同操作系统有不同的实现,这对于跨平台的应用非常有帮助。

对于C语言,我们可以用dlsym去修改动态链接的函数(备注:dlsym函数是GNU扩展),但dlsym的最大劣势仍然是只能在Linux下使用,那么,有没有一套跨平台的方案,可以在所有平台上运行呢?其实也是有的。

那就是通过宏定义的方式,将malloc/free这些函数替换成我们自己实现的钩子函数。比如我们有如下定义:

//mcheck.h
#ifndef _MCHECK_H_
#define _MCHECK_H_#include<stddef.h>void mcheck_initialize();
void mcheck_terminate();void *malloc_hook(size_t size, const char *file, int line);
void *calloc_hook(size_t nmemb, size_t size, const char *file, int line);
void *realloc_hook(void *ptr, size_t size, const char *file, int line);
void free_hook(void *p, const char *file, int line);#define malloc(size)            malloc_hook(size, __FILE__, __LINE__)
#define calloc(nmemb, size)     calloc_hook(nmemb, size, __FILE__, __LINE__)
#define realloc(ptr, size)       realloc_hook(ptr, size, __FILE__, __LINE__)
#define free(p)                 free_hook(p, __FILE__, __LINE__)#endif

由于宏定义是直接替换,因此,有了上面的代码,在执行malloc的时候,实际上执行的是malloc_hook函数。而我们只需要在实现malloc_hook/free_hook的时候加上一些统计信息就行了。

在此之前,我们封装一个链表,用来存储每次申请内存的地址以及申请内存的大小,在每次申请内存的时候,向链表添加一条数据,每次释放的时候,将对应的记录删除掉,那么,当程序结束,如果链表还有数据,那就是没有释放的泄露部分的内存。

当然你也可以用其他的数据接口来存储,这里为了简单演示,就直接使用链表了。

// meminfo.h
#ifndef _MEMINFO_H_
#define _MEMINFO_H_#include<stddef.h>
#include<stdio.h>
#include<stdlib.h>typedef enum mcheck_errcode_t
{MCHECK_SUCCESS,MCHECK_FAILED,
}mcheck_errcode_t;typedef struct mcheck_caller_t
{const char *file;int line;const char *func;
} mcheck_caller_t;typedef struct mcheck_meminfo {void    *address;size_t  size;mcheck_caller_t caller;
}mcheck_meminfo;typedef struct mcheck_mem_list {mcheck_meminfo mem_info;struct mcheck_mem_list *next;
}mcheck_mem_list;int mcheck_mem_list_create(mcheck_mem_list **list);
int mcheck_mem_list_add(mcheck_mem_list *mlist, mcheck_meminfo mem_info);
mcheck_mem_list *mcheck_mem_list_get(mcheck_mem_list *mlist, void *address);
int mcheck_mem_list_delete(mcheck_mem_list *mlist, void *address);
int mcheck_list_size(mcheck_mem_list *mlist);
void mcheck_list_report_leak(mcheck_mem_list *mlist);
void mcheck_list_destory(mcheck_mem_list *mlist);
void init_report_file();#endif

定义如下:

//meminfo.c
#include "meminfo.h"int mcheck_mem_list_create(mcheck_mem_list **mlist){if (*mlist != NULL) {mcheck_list_destory(*mlist);}*mlist = (mcheck_mem_list *)calloc(1, sizeof(mcheck_mem_list));if (*mlist == NULL) {return MCHECK_FAILED;}(*mlist)->next = NULL;return MCHECK_SUCCESS;
}int mcheck_mem_list_add(mcheck_mem_list *mlist, mcheck_meminfo mem_info)
{mcheck_mem_list *node = NULL;mcheck_mem_list_create(&node);node->mem_info = mem_info;if (mlist == NULL){mlist = node;return MCHECK_SUCCESS;}while (mlist->next != NULL){mlist = mlist->next;}mlist->next = node;return MCHECK_SUCCESS;
}mcheck_mem_list *mcheck_mem_list_get(mcheck_mem_list *mlist, void *address){if (mlist == NULL) {return NULL;}mcheck_mem_list *node = mlist;while (mlist != NULL) {if (address == mlist->mem_info.address) {return node;}mlist = mlist->next;}return NULL;
}int mcheck_mem_list_delete(mcheck_mem_list *mlist, void *address){if (mlist == NULL) {return MCHECK_FAILED;}mcheck_mem_list *current = mlist;mcheck_mem_list *prev = mlist;while (current != NULL) {if (current->mem_info.address == address) {if (mlist == current) {if (current->next = NULL) {mlist = NULL;} else {mlist = mlist->next;}} else {prev->next = current->next;}free(current);return MCHECK_SUCCESS;}prev = current;current = current->next;}return MCHECK_FAILED;
}int mcheck_list_size(mcheck_mem_list *mlist){if (mlist == NULL)   {return 0;}int size = 0;while(mlist->next != NULL){size++;mlist = mlist->next;}return size;
}void mcheck_list_destory(mcheck_mem_list *mlist){if (mlist == NULL) {return;}mcheck_mem_list *current = mlist;mcheck_mem_list *prev = mlist;while (prev != NULL) {current = current->next;free(prev);prev = current;}mlist = NULL;
}static char *get_report_filename(){char *fname = getenv("MCHECK_TRACE");if (fname == NULL) {fname = "mcheck.rpt";}return fname;
}void init_report_file(){char *fname = get_report_filename();FILE *fp = NULL;fp = fopen(fname, "w+");fclose(fp);
}static void write_report_file(char *message){char *fname = get_report_filename();FILE *fp = NULL;fp = fopen(fname, "a+");fprintf(fp, "%s\n", message);fflush(stdout);fclose(fp);
}void mcheck_list_report_leak(mcheck_mem_list *mlist){if (mcheck_list_size(mlist) == 0){write_report_file("All memory was free, congratulations, well done!");return;}write_report_file("Memory Not Free:");write_report_file("-----------------------------");write_report_file("\tAddress\t\tSize\t\tCaller");mlist = mlist->next;while (mlist != NULL){mcheck_meminfo mem_info = mlist->mem_info;char message[1024] = {0};sprintf(message, "\t%p\t%lu\tat\t%s:%d[%s]", mem_info.address, mem_info.size, mem_info.caller.file, mem_info.caller.line, mem_info.caller.func);write_report_file(message);mlist = mlist->next;}
}

以上代码逻辑比较简单 ,就不一一解释了。接下来实现一下钩子函数:

#include<stdio.h>
#include<malloc.h>
#include "meminfo.h"static mcheck_mem_list *mlist = NULL;void mcheck_initialize()
{init_report_file();mcheck_mem_list_create(&mlist);
}void mcheck_terminate(){mcheck_list_report_leak(mlist);mcheck_list_destory(mlist);
}void *malloc_hook(size_t size, const char *file, int line)
{void *p = malloc(size);char buff[128] = {0};mcheck_meminfo meminfo = {0};mcheck_caller_t caller = {0};caller.file = file;caller.line = line;caller.func = "malloc";meminfo.address = p;meminfo.size = size;meminfo.caller = caller;mcheck_mem_list_add(mlist, meminfo);return p;
}void *calloc_hook(size_t nmemb, size_t size, const char *file, int line)
{void *p = calloc(nmemb, size);char buff[128] = {0};mcheck_meminfo meminfo = {0};mcheck_caller_t caller = {0};caller.file = file;caller.line = line;caller.func = "calloc";meminfo.address = p;meminfo.size = nmemb*size;meminfo.caller = caller;mcheck_mem_list_add(mlist, meminfo);return p;
}void *realloc_hook(void *ptr, size_t size, const char *file, int line)
{void *p = realloc(ptr, size);char buff[128] = {0};mcheck_meminfo meminfo = {0};mcheck_caller_t caller = {0};caller.file = file;caller.line = line;caller.func = "realloc";meminfo.address = p;meminfo.size = size;meminfo.caller = caller;mcheck_mem_list_add(mlist, meminfo);mcheck_mem_list_delete(mlist, ptr);return p;
}void free_hook(void *p, const char *file, int line){mcheck_mem_list_delete(mlist, p);free(p);
}

如上所示,我们会在每次申请内存之前,收集其调用栈信息,并且封装了mcheck_initializemcheck_terminate两个接口函数,我们只需要在程序里调用这两个函数,就能检测出内存泄露的问题。

类似与下面这种:

#include <mcheck.h>int main(void){mcheck_initialize();//your codemcheck_terminate();return 0;
}

下面我们用一个具体的示例演示一下:

#include "mcheck.h"int main(void){mcheck_initialize();void *p1 = malloc(10);void *p2 = malloc(20);free(p1);//free(p2);void *p3 = malloc(30);free(p3);void *p4 = calloc(1, 64);void *p5 = malloc(32);void *p6 = realloc(p5, 128);mcheck_terminate();return 0;

我们注意在第1行包含了头文件,并在第4行和14行分别调用了mcheck的接口,这样的话,就可以检测出这个过程中出现的内存泄露问题,以上代码运行会产生一个名为mcheck.rpt的报告,内容如下:

Memory Not Free:
-----------------------------Address		Size		Caller0x1fde0b0	20	at	mcheck_sample.c:6[malloc]0x1fde300	64	at	mcheck_sample.c:11[calloc]0x1fde390	128	at	mcheck_sample.c:13[realloc]

它告诉我们第6,11,13行分别出现了内存泄露,大小是多少,调用的那么函数申请的内存,还是比较详细的。

但是这种方式也有缺陷。首先就是调用栈只有一层,不能打印出更深层的调用栈,不利于复杂程序的问题排查。其次是如果要使mcheck生效,必须每个.c里都要include该头文件,对于第三方库是没有办法检测到的,因此使用面也是比较有限。


本专栏知识点是通过<零声教育>的系统学习,进行梳理总结写下文章,对C/C++课程感兴趣的读者,可以点击链接,查看详细的服务:C/C++Linux服务器开发/高级架构师

http://www.yayakq.cn/news/449906/

相关文章:

  • 网站集约化建设纪要珠海工商网上登记平台
  • 和龙建设局网站WordPress 蜘蛛池
  • 电商平台网站开发文档注册网站卖东西
  • 应用网站如何做wordpress asp.net
  • 西安做网站电话四川中天建设有限公司网站
  • ps做网站好看的logo外包网络安全
  • 发果怎么做视频网站制作动画网站模板
  • 网站建设开发综合实训小结python做网站开发
  • 网站建设与管理题库京东网站建设案例论文
  • 专业网站设计是什么购物网站二级页面模板
  • 太原网站建站模板新房地产网站开发
  • 能免费创建网站吗朝阳市做网站
  • 福州开发企业网站本科学历提升
  • 网站备案信息传wordpress自带的会员中心
  • wordpress上传错误500南宁网站排名优化公司
  • 网站建设实习困难废品回收网站怎么做网站优化
  • 九九人才网赣州招聘手机优化大师官方免费下载
  • 山西网站建设营销qq深圳网站建设 东莞网站建设
  • 重庆网站商城微信朋友圈广告投放价格表
  • 中企动力双语网站绥中建设厅网站
  • 如何写网站优化目标南海小程序网站开发
  • 怎么用node做网站阿里云空间如何安装wordpress
  • 网站建设技术文档网站防止恶意注册
  • 网站常用的js效果大秀
  • asp.net 做网站文章是怎么存储的去哪里做网站
  • 注册域名不建设网站网页设计你若安好便是晴天作业
  • 网站内容建设的布局岳阳建设局网站
  • 免费的活动策划网站适合做设计公司的名字
  • php ajax网站开发典型实例 pdf信阳做网站公司汉狮价格
  • 网站建设条款Wordpress news模板