ibevent 定制——libevent 定制内存分配

libevent 定制内存分配

默认情况下,libevent 使用 C 库的内存管理函数在堆上分配内存。通过提供 mallocreallocfree 的替代函数,可以让 libevent 使用其他的内存管理器。希望 libevent 使用一个更高效的分配器时;或者希望 libevent 使用一个工具分配器,以便检查内存泄漏时,可能需要这样做。

libevent允许用户(库的使用者)定制自己的内存分配函数。

首先,如果要定制自己的内存分配函数,就得在一开始配置编译libevent库是,不能加入--disable-malloc-replacement选项。默认情况下,是没有这个选项的。如果加入了这个选项,那么将会在生成的event-config.h中,定义_EVENT_DISABLE_MM_REPLACEMENT这个宏。下面是libevent内存分配函数的声明(在mm-internal.h文件):

/** Copyright (c) 2007-2012 Niels Provos and Nick Mathewson** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions* are met:* 1. Redistributions of source code must retain the above copyright*    notice, this list of conditions and the following disclaimer.* 2. Redistributions in binary form must reproduce the above copyright*    notice, this list of conditions and the following disclaimer in the*    documentation and/or other materials provided with the distribution.* 3. The name of the author may not be used to endorse or promote products*    derived from this software without specific prior written permission.** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
#ifndef MM_INTERNAL_H_INCLUDED_
#define MM_INTERNAL_H_INCLUDED_#include <sys/types.h>#ifdef __cplusplus
extern "C" {
#endif#ifndef EVENT__DISABLE_MM_REPLACEMENT
/* Internal use only: Memory allocation functions. We give them nice short* mm_names for our own use, but make sure that the symbols have longer names* so they don't conflict with other libraries (like, say, libmm). *//** Allocate uninitialized memory.** @return On success, return a pointer to sz newly allocated bytes.*     On failure, set errno to ENOMEM and return NULL.*     If the argument sz is 0, simply return NULL.*/
EVENT2_EXPORT_SYMBOL
void *event_mm_malloc_(size_t sz);/** Allocate memory initialized to zero.** @return On success, return a pointer to (count * size) newly allocated*     bytes, initialized to zero.*     On failure, or if the product would result in an integer overflow,*     set errno to ENOMEM and return NULL.*     If either arguments are 0, simply return NULL.*/
EVENT2_EXPORT_SYMBOL
void *event_mm_calloc_(size_t count, size_t size);/** Duplicate a string.** @return On success, return a pointer to a newly allocated duplicate*     of a string.*     Set errno to ENOMEM and return NULL if a memory allocation error*     occurs (or would occur) in the process.*     If the argument str is NULL, set errno to EINVAL and return NULL.*/
EVENT2_EXPORT_SYMBOL
char *event_mm_strdup_(const char *str);EVENT2_EXPORT_SYMBOL
void *event_mm_realloc_(void *p, size_t sz);
EVENT2_EXPORT_SYMBOL
void event_mm_free_(void *p);
#define mm_malloc(sz) event_mm_malloc_(sz)
#define mm_calloc(count, size) event_mm_calloc_((count), (size))
#define mm_strdup(s) event_mm_strdup_(s)
#define mm_realloc(p, sz) event_mm_realloc_((p), (sz))
#define mm_free(p) event_mm_free_(p)
#else
#define mm_malloc(sz) malloc(sz)
#define mm_calloc(n, sz) calloc((n), (sz))
#define mm_strdup(s) strdup(s)
#define mm_realloc(p, sz) realloc((p), (sz))
#define mm_free(p) free(p)
#endif#ifdef __cplusplus
}
#endif#endif

这些内存分配函数是给libevent使用的,而非用户(从这些接口声明在mm-internal.h文件中就可以看到这一点)。libevent的其他函数要申请内存就调用mm_malloc之类的宏定义。如果一开始在配置的时候(event-config.h)就禁止用户定制自己的内存分配函数,那么就把这些宏定义为C语言标准内存分配函数。
当然,即使没有禁止,如果用户没有定制自己的内存分配函数,最终还是调用C语言的标准内存分配函数。这一点在event_mm_xxxx这些函数的实现上可以看到。
定制内存函数的声明在include/event2/event.h:

#if !defined(EVENT__DISABLE_MM_REPLACEMENT) || defined(EVENT_IN_DOXYGEN_)
/**Override the functions that Libevent uses for memory management.Usually, Libevent uses the standard libc functions malloc, realloc, andfree to allocate memory.  Passing replacements for those functions toevent_set_mem_functions() overrides this behavior.Note that all memory returned from Libevent will be allocated by thereplacement functions rather than by malloc() and realloc().  Thus, if youhave replaced those functions, it will not be appropriate to free() memorythat you get from Libevent.  Instead, you must use the free_fn replacementthat you provided.Note also that if you are going to call this function, you should do sobefore any call to any Libevent function that does allocation.Otherwise, those functions will allocate their memory using malloc(), butthen later free it using your provided free_fn.@param malloc_fn A replacement for malloc.@param realloc_fn A replacement for realloc@param free_fn A replacement for free.**/
EVENT2_EXPORT_SYMBOL
void event_set_mem_functions(void *(*malloc_fn)(size_t sz),void *(*realloc_fn)(void *ptr, size_t sz),void (*free_fn)(void *ptr));
/** This definition is present if Libevent was built with support forevent_set_mem_functions() */
#define EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED
#endif

其定义在event.c中:

void
event_set_mem_functions(void *(*malloc_fn)(size_t sz),void *(*realloc_fn)(void *ptr, size_t sz),void (*free_fn)(void *ptr))
{mm_malloc_fn_ = malloc_fn;mm_realloc_fn_ = realloc_fn;mm_free_fn_ = free_fn;
}

定制自己的内存分配函数需要注意的一些地方:

  • 替换内存管理函数影响libevent 随后的所有分配、调整大小和释放内存操作。所以必须保证在调用任何其他libevent函数之前进行定制。否则,libevent可能用定制的free函数释放C语言 库的malloc函数分配的内存
  • mallocrealloc函数返回的内存块应该具有和C库返回的内存块一样的地址对齐
  • realloc函数应该正确处理realloc(NULL, sz)(也就是当作malloc(sz)处理)
  • realloc函数应该正确处理realloc(ptr, 0)(也就是当作free(ptr)处理)
  • 你的 free 函数不必处理 free(NULL)
  • 你的 malloc 函数不必处理 malloc(0)
  • 如果在多个线程中使用libevent,替代的内存管理函数需要是线程安全的
  • 如果要释放由libevent函数分配的内存,并且已经定制了mallocrealloc函数,那么就应该使用定制的free函数释放。否则将会C语言标准库的free函数释放定制内存分配函数分配的内存,这将发生错误。所以三者要么全部不定制,要么全部定制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/82195.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

有多条业务线,mysql建多库多表比较好还是一个库多个表比较好呢?

选择使用多库多表还是一个库多个表&#xff0c;取决于你的具体情况和需求。以下是一些考虑因素&#xff1a; 数据隔离&#xff1a;如果每条业务线需要完全独立的数据隔离&#xff0c;例如不同业务线的数据不会相互关联或共享&#xff0c;那么使用多库可以更好地实现数据隔离。 …

JavaWeb 学习笔记 3:Servlet

JavaWeb 学习笔记 3&#xff1a;Servlet 1.简介 Servlet 是 JavaEE 定义的一套 Web 应用开发标准&#xff08;接口&#xff09;&#xff0c;实现了该技术的 Web 服务器软件&#xff08;如 Tomcat&#xff09;上可以运行一个 Servlet 容器&#xff0c;只要我们使用 Servlet 技…

Python 移动文件到指定路径

需求&#xff1a;将指定的文件从指定目录移动到用户指定的目标目录。 shutil 是 Python 标准库中的一个模块&#xff0c;它提供了许多文件和文件集合的高级操作。基本上&#xff0c;它可以帮助我们执行文件操作&#xff0c;例如复制、移动、更名和删除。它旨在与 os 模块一起使…

【测试开发】基础篇 · 专业术语 · 软件测试生命周期 · bug的描述 · bug的级别 · bug的生命周期 · 处理争执

【测试开发】基础篇 文章目录 【测试开发】基础篇1. 软件测试生命周期1.1 软件生命周期1.2 软件测试生命周期 2. 描述bug3. 如何定义bug的级别3.1 为什么要对bug进行级别划分3.2 bug的一些常见级别 4. bug的生命周期5. 产生争执这么怎么办&#xff08;处理人际关系&#xff09;…

ChatGPT:URL编码问题——如何正确进行URL编码以处理特殊字符

ChatGPT&#xff1a;URL编码问题——如何正确进行URL编码以处理特殊字符 报错&#xff1a; URISyntaxException: Malformed escape pair at index 192: http://Center/Question/questionList.html?seaKey%E6%8D%AE%E7%BB%9F%E8%AE%A1%EF%BC%8C%E5%9B%A0%E7%81%AB%E7%81%BE%E6%…

服务器数据恢复-LINUX操作系统下各文件系统误删除/格式化数据的恢复方案

服务器数据恢复环境&#xff1a; 基于EXT2/EXT3/EXT4/Reiserfs/Xfs文件系统的Linux操作系统。 服务器故障&#xff1a; LINUX操作系统下误删除/格式化数据。 服务器数据恢复过程&#xff1a; 1、首先会检测服务器是否存在硬件故障&#xff0c;如果检测出硬件故障&#xff0c;交…

Linux之jar包之启动与停止脚本

Linux之jar包之启动与停止脚本 一、使用说明二、脚本代码 一、使用说明 启动 ./service.sh start关闭 ./service.sh stop二、脚本代码 #!/bin/bash #这里可替换为你自己的执行程序&#xff0c;其他代码无需更改 APP_NAMEmxy_system-0.0.1-SNAPSHOT.jar # shellcheck disabl…

9.18算法

机器人重物1126 注意编号是方块的&#xff0c;而不是格点的 及如果为n*m的矩阵&#xff0c;需要开(n1)*(m1)的矩阵 //如果没有转向&#xff0c;就是走迷宫&#xff0c;结合记忆化&#xff0c;如果这个点之前走过就不走了 //又转向的话&#xff0c;就用一个变量记录当前转向&…

量化分析革新金融服务软件的三种方式

金融服务软件行业爱死量化分析了。 为什么呢&#xff1f;因为在这个本质上不可预测的行业中&#xff0c;量化分析提供了一种确定性&#xff0c;或者至少是类似于确定性的东西。 市场总是在变动&#xff0c;利润也起伏不定。交易达成了&#xff0c;然后落空&#xff0c;又再次…

Golang Linux 安装与环境变量配置

下载 Go 二进制包 wget https://dl.google.com/go/go1.21.1.linux-amd64.tar.gz 解压文件并将其移至 /usr/local 目录 sudo tar -C /usr/local -xzf go1.20.1.linux-amd64.tar.gz -C 选项解压文件到 /usr/local 目录&#xff0c;查看 /usr/local/go 目录的内容 将 Go 二进…

19 视图定义 union 是根据第一个 select 字段列表顺序,来进行 merge 的

前言 这个问题主要是 在之前存在这样的一个问题, 在生产环境上面 按照 我的直观理解, mysql 应该是根据 key 进行 merge, 所以 select 的顺序应该是 “不重要”??, 但是 结果我理解错了 然后 线上的查询也出现了问题, 发现很奇怪的问题, 明明 key01 列 是 id, 但是有一部…

深度学习——线性神经网络一

深度学习——线性神经网络一 文章目录 前言一、线性回归1.1. 线性回归的基本元素1.1.1. 线性模型1.1.2. 损失函数1.1.3. 解析解1.1.4. 随机梯度下降1.1.5. 用模型进行预测 1.2. 向量化加速1.3. 正态分布与平方损失1.4. 从线性回归到深度网络 二、线性回归的从零开始实现2.1. 生…

Java面试题整理(带答案)

目录 TCP和UDP的区别 get和post的区别 Cookie和session的区别 Java的基本类型有哪些&#xff1f; 抽象类和接口区别&#xff1f; 对于堆栈的理解 和equals区别 如何理解Java多态&#xff1f; 创建线程都有哪些方式 脏读、不可重复度、幻读都是什么&#xff1f; Jav…

数据治理-数据仓库环境

数据仓库环境包括一系列组织起来以满足企业需求的架构组件&#xff0c;从源系统流动到数据暂存区&#xff0c;数据可以在这里被清晰&#xff0c;当数据集成并存储在数据仓库或操作数据存储中时&#xff0c;可以对其进行补充丰富。在数据仓库中&#xff0c;可以通过数据集市或数…

多线程详解(上)

文章目录 一、线程的概念1&#xff09;线程是什么2&#xff09;为甚要有线程&#xff08;1&#xff09;“并发编程”成为“刚需”&#xff08;2&#xff09;在并发编程中, 线程比进程更轻量. 3&#xff09;线程和进程的区别 二、Thread的使用1&#xff09;线程的创建继承Thread…

[deeplearning]pytorch实现softmax多分类问题预测训练

写在前面&#xff1a;俺这两天也是刚刚加入实验室&#xff0c;因为之前的学习过程中用到更多的框架是tensorflow&#xff0c;所以突然上手pytorch多少有些力不从心了。 这两个框架的主要区别在与tensorflow更偏向于工业使用&#xff0c;所以里面的很多函数和类都已经封装得很完…

算法通关村-----链表中环的问题

环形链表 问题描述 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中…

Reactor 第十二篇 WebFlux集成PostgreSQL

1 引言 在现代的应用开发中&#xff0c;数据库是存储和管理数据的关键组件。PostgreSQL 是一种强大的开源关系型数据库&#xff0c;而 WebFlux 是 Spring 框架提供的响应式编程模型。本文将介绍如何使用 Reactor 和 WebFlux 集成 PostgreSQL&#xff0c;实现响应式的数据库访问…

【chrome扩展开发】消息通讯之onMessage消息监听

前言 chrome.runtime.onMessage.addListener 是 Chrome 扩展程序中用于监听其他模块发送的消息并做出响应的 API 当从扩展进程 (by runtime.sendMessage) 或内容脚本 (by tabs.sendMessage)发送消息时触发 语法 chrome.runtime.onMessage.addListener(callback: function, )ca…

使用Scrapy构建高效的网络爬虫

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 Scrapy是一个强大的Pyth…