malloc相关知识
-
减少 curl 中内存分配操作(malloc)今天我在 libcurl 内部又做了一个小改动,使其做更少的 malloc。这一次,泛型链表函数被转换成更少的 malloc (这才是链表函数应有的方式,真的)。研究 malloc几周前我开始研究内存分配。这很容易,因为多年前我们 curl 中就已经有内存调试和日志记录系统了。使用 curl 的调试版本,并在我的构建目录中运行此脚本:#!/bin/shexport CURL_MEMDEBUG=$HOME/tmp/curlmem.log./src/curl http://localhost./tests/memanalyze.pl -v $HOME/tmp/curlmem.log对于 curl 7.53.1,这大约有 115 次内存分配。这算多还是少?内存日志非常基础。为了让你有所了解,这是一个示例片段:MEM getinfo.c:70 free((nil))MEM getinfo.c:73 free((nil))MEM url.c:294 free((nil))MEM url.c:297 strdup(0x
-
减少 curl 中内存分配操作(malloc)今天我在 libcurl 内部又做了一个小改动,使其做更少的 malloc。这一次,泛型链表函数被转换成更少的 malloc (这才是链表函数应有的方式,真的)。研究 malloc几周前我开始研究内存分配。这很容易,因为多年前我们 curl 中就已经有内存调试和日志记录系统了。使用 curl 的调试版本,并在我的构建目录中运行此脚本:#!/bin/shexport CURL_MEMDEBUG=$HOME/tmp/curlmem.log ./src/curl http://localhost ./tests/memanalyze.pl -v $HOME/tmp/curlmem.log对于 curl 7.53.1,这大约有 115 次内存分配。这算多还是少?内存日志非常基础。为了让你有所了解,这是一个示例片段:MEM getinfo.c:70 free((nil)) MEM getinfo.c:73 free((nil)) MEM&
-
听说new,delete调用了malloc,free?前言:C分配和释放动态内存的方式分别是malloc与free,malloc用于分配堆内存,free用于释放堆内存;C++定义了两个运算符来分配和释放动态内存,运算符new分配堆内存,运算符delete释放new分配的堆内存;1、new与delete用法简单介绍new:用法一: TypeName ∗pointer=new TypeName()用法一:\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ TypeName\ \ *pointer=new\ \ TypeName()用法一: TypeName ∗pointer=new TypeName()末尾小括号()可有可无,动态分配内存的对象是默认初始化的,调用默认构造函数,()用于初始化的,new返回TypeName类型的指针,如:vector是泛型类模板,vector<int>是具体类型就与basic_string与string的关系一样double *p = new
-
c语言内存泄漏检测方法之封装malloc,free详解evn:gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.10)摘要:方法简介如何检测项目中是否有内存泄漏(附代码)如何定位项目中的内存泄漏(附代码)心得和建议1.方法简介 这种方法原理很简单, 正常情况下程序启动到正常终止malloc和free调用的次数应该相同, 如果malloc调用次数>free调用次数, 那么项目中就会出现内存泄漏。基于上述原理, 我们可以自己封装一套malloc和free,然后在里面做点手脚即可, 当然过程中还是有一些地方需要注意,详情请看下文~2.如何检测项目中是否有内存泄漏 如果仅仅是确定项目中是否有内存泄漏的话,可以定义1个计数器count, 放在我们重新封装的test_malloc, test_free函数中。当调用test_malloc的时候, count++, 当调用free的时候count--。当程序结束运行的时候, 如果count大于0, 则说明有内存泄漏; 如果count等于0说明没有内存泄漏
malloc相关课程
malloc相关教程
- 1.1 手动内存管理 在计算机发展的早期,编程语言提供了手动内存管理的机制,例如 C 语言,提供了用于分配和释放的函数 malloc 和 free,如下所示:#include <stdlib.h>void *malloc(size_t size);void free(void *p);函数 malloc 分配指定大小 size 的内存,返回内存的首地址函数 free 释放之前申请的内存程序员负责保证内存管理的正确性:使用 malloc 申请一块内存后,如果不再使用,需要使用 free 将其释放,示例如下:#include <stdlib.h>void test(){ void *p = malloc(10); 访问 p 指向的内存区域; free(p);}int main(){ test();}使用 malloc(10) 分配一块大小为 10 个字节的内存区域使用 free§ 释放这块内存区域如果忘记释放之前使用 malloc 申请的内存,则会导致可用内存不断减少,这种现象被称为 “内存泄漏”,示例如下:#include <stdio.h>#include <stdlib.h>void test(){ void *p = malloc(10); 访问 p 指向的内存区域;}int main(){ while (1) test();}在函数 test 中,使用 malloc 申请一块内存但是使用完毕后,忘记释放了这块内存在函数 main 中,循环调用函数 test()每次调用函数 test(),都会造成内存泄漏最终,会耗尽所有的内存
- 3. 示例程序 #include <stdio.h>#include <stdlib.h>int main(){ int *x; printf("x value: %p, x address: %p, *x value: %d\n", x, &x, *x); x = (int *)malloc(sizeof(x)); printf("x value: %p, x address: %p, *x value: %d\n", x, &x, *x); *x = 10; printf("x value: %p, x address: %p, *x value: %d\n", x, &x, *x); free(x); return 0;}运行结果:x value: 0x7fffeac6bd50, x address: 0x7fffeac6bc60, *x value: 1x value: 0x7fffe3916270, x address: 0x7fffeac6bc60, *x value: 0x value: 0x7fffe3916270, x address: 0x7fffeac6bc60, *x value: 10程序中声明了一个整数型的指针,然后对这个指针分配了一块内存。把这个分配好的内存地址给了指针变量。然后对这个地址所表示的变量进行赋值。最后再回收分配的内存。
- 1. Redis 介绍与安装 首先我们在 CentOS7.8 的系统上源码编译安装 redis-5.0 的最新版。按照下列步骤进行:安装 gcc 等编译工具,下载 redis 5 的最新源码并解压:[root@server2 shen]# wget http://download.redis.io/releases/redis-5.0.9.tar.gz--2020-06-27 13:10:23-- http://download.redis.io/releases/redis-5.0.9.tar.gzResolving download.redis.io (download.redis.io)... 109.74.203.151Connecting to download.redis.io (download.redis.io)|109.74.203.151|:80... connected.HTTP request sent, awaiting response... 200 OKLength: 1986574 (1.9M) [application/x-gzip]Saving to: ‘redis-5.0.9.tar.gz’100%[=========================================================================================================================================>] 1,986,574 12.9KB/s in 2m 11s 2020-06-27 13:12:35 (14.8 KB/s) - ‘redis-5.0.9.tar.gz’ saved [1986574/1986574][root@server2 shen]# tar xzf redis-5.0.9.tar.gz进入 redis 源码目录,直接安装:[root@server2 shen]# cd redis-5.0.9[root@server2 redis-5.0.9]# make MALLOC=libc PREFIX=/usr/local/redis install添加 redis 命令路径:[root@server2 redis-5.0.9]# cat /etc/profile...# 添加下面两行内容REDIS_HOME=/usr/local/redisexport PATH=$REDIS_HOME/bin:$PATH[root@server2 redis-5.0.9]# source /etc/profile[root@server2 redis-5.0.9]# which redis-cli/usr/local/redis/bin/redis-cli添加并修改 redis.conf 配置文件:[root@server2 redis-5.0.9]# mkdir /etc/redis[root@server2 redis-5.0.9]# cp redis.conf /etc/redis[root@server2 redis-5.0.9]# cat /etc/redis# ...# 修改第一处,改为后台守护进程方式启动daemonize yes# ...# 修改端口,比如改为6777port 6777# ...# 需要密码# requirepass foobaredrequirepass spyinx# ...# 允许通过公网访问该redis# bind 127.0.0.1bind 0.0.0.0加入 systemd 服务,统一管理:[root@server2 redis-5.0.9]# cat /etc/systemd/system/redis.service[Unit]Description=RedisAfter=network.target [Service]Type=forkingExecStart=/usr/local/redis/bin/redis-server /etc/redis/redis.confExecReload=/bin/kill -s HUP $MAINPIDExecStop=/usr/local/redis/bin/redis-cli -p 6777 shutdownPrivateTmp=true [Install]WantedBy=multi-user.target[root@server2 redis-5.0.9]# systemctl start redis[root@server2 redis-5.0.9]# systemctl status redis● redis.service - Redis Loaded: loaded (/etc/systemd/system/redis.service; disabled; vendor preset: disabled) Active: active (running) since Sat 2020-06-27 14:08:44 CST; 3s ago Process: 7080 ExecStart=/usr/local/redis/bin/redis-server /etc/redis/redis.conf (code=exited, status=0/SUCCESS) Main PID: 7081 (redis-server) CGroup: /system.slice/redis.service └─7081 /usr/local/redis/bin/redis-server 0.0.0.0:6777Jun 27 14:08:44 server2 systemd[1]: Starting Redis...Jun 27 14:08:44 server2 redis-server[7080]: 7080:C 27 Jun 2020 14:08:44.938 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0OoJun 27 14:08:44 server2 redis-server[7080]: 7080:C 27 Jun 2020 14:08:44.938 # Redis version=5.0.9, bits=64, commit=00000000, ...startedJun 27 14:08:44 server2 redis-server[7080]: 7080:C 27 Jun 2020 14:08:44.938 # Configuration loadedJun 27 14:08:44 server2 systemd[1]: Started Redis.Hint: Some lines were ellipsized, use -l to show in full.# 设置开机启动[root@server2 redis-5.0.9]# systemctl enable redisCreated symlink from /etc/systemd/system/multi-user.target.wants/redis.service to /etc/systemd/system/redis.service.最后测试下 redis 服务是否能正常工作:[root@server2 redis-5.0.9]# redis-cli -p 6777127.0.0.1:6777> auth spyinxOK127.0.0.1:6777> ping "hello, world""hello, world"127.0.0.1:6777> set hello worldOK127.0.0.1:6777> get hello"world"127.0.0.1:6777> 完成 redis 服务搭建后我们就可以开始 redis 服务的使用了。
- 1. django-celery 框架实战 我们使用 django-celery 框架完成2个小实验,简单体验下 celery 框架的功能。首先准备好实验环境,包括安装 django-celery 等依赖的模块以及完成初始配置代码。按照以下步骤进行:安装依赖模块:包括 django-celery 等;(django-manual) [root@server first_django_app]# pip install django-celery注意: 如果想要使用 Django 的 ORM 来存储结果,想要安装 django-celery-results 插件;安装好 redis 服务,使用源码或者 yum 安装即可;(django-manual) [root@server first_django_app]# yum install redis推荐使用源码安装方式,可以安装高版本的 redis。最后我在本机上安装了 redis 5.0 版本的服务,如下:(django-manual) [root@server first_django_app]# redis-server --versionRedis server v=5.0.7 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=5cb8e5612a04130d(django-manual) [root@server first_django_app]# systemctl status redis● redis.service - Redis Loaded: loaded (/etc/systemd/system/redis.service; disabled; vendor preset: disabled) Drop-In: /etc/systemd/system/redis.service.d └─limit.conf Active: active (running) since 一 2020-01-13 22:41:09 CST; 3 months 28 days ago Main PID: 1707 (redis-server) CGroup: /system.slice/redis.service └─1707 /usr/local/bin/redis-server 127.0.0.1:6379新增一个处理异步任务的应用:async_tasks,另外设置相应的 settings.py 中的配置:(django-manual) [root@server first_django_app]# django-admin startapp async_tasks在 async_tasks 目录下准备一个 tasks.py 文件在,这个代码里面会放一些需要异步处理的任务:# 代码位置:async_tasks/tasks.py# Create your tasks herefrom __future__ import absolute_import, unicode_literalsimport timefrom celery import shared_task@shared_taskdef add(x, y): time.sleep(10) return x + y最后,为了能启动 celery 服务,我们需要在 Django 项目下 settings.py 的同级目录下添加一个 celery.py 文件 (必须这样命名) :# 代码位置:first_django_app/celery.pyfrom __future__ import absolute_import, unicode_literals import osfrom celery import Celeryfrom django.conf import settings# 设置环境变量os.environ.setdefault("DJANGO_SETTINGS_MODULE", "first_django_app.settings")#创建celery应用app = Celery('first_django_app')app.config_from_object('django.conf:settings', namespace='CELERY')#如果在工程的应用中创建了 tasks.py 模块,那么Celery应用就会自动去检索创建的任务。app.autodiscover_tasks(lambda:settings.INSTALLED_APPS)# 代码位置:first_django_app/__init__.pyfrom __future__ import absolute_import# This will make sure the app is always imported when# Django starts so that shared_task will use this app.from .celery import app as celery_app接下里我们在 settings.py 中增加 celery 的相关配置,包括设置 broker 等# 代码位置:first_django_app/settings.pyINSTALLED_APPS = [ # ... 'djcelery', # 注册应用 'hello_app', 'async_tasks'] import djcelerydjcelery.setup_loader()CELERY_TIMEZONE='Asia/Shanghai'CELERY_BROKER_URL='redis://127.0.0.1:6379/0'CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/0' # BACKEND配置,这里使用redisCELERY_RESULT_SERIALIZER = 'json' CELERY_IMPORTS = ('async_tasks.tasks')CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler' ###测试环境。下面第一个以交互式方式启动 celery,后续则是以守护进程方式启动。# 交互式方式启动(django-manual) [root@server first_django_app]# celery -A first_django_app worker -l info...# 以守护进程方式启动(django-manual) [root@server first_django_app]# celery multi start w1 -A first_django_app --concurrency=4 -l info --logfile=/root/test/celerylog.log --pidfile=celerypid.pidcelery multi v4.4.2 (cliffs)> Starting nodes...> w1@server: OK(django-manual) [root@server first_django_app]# celery multi stop w1 -A first_django_app -l infocelery multi v4.4.2 (cliffs)> w1@server: DOWN启动服务之后,我们在另一个连接窗口进行测试,使用 Django 的 shell 交互模式调用 celery 的 task。(django-manual) [root@server first_django_app]# python manage.py shellPython 3.8.1 (default, Dec 24 2019, 17:04:00) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linuxType "help", "copyright", "credits" or "license" for more information.(InteractiveConsole)>>> from async_tasks.tasks import add>>> add.delay(8, 10)<AsyncResult: c41bee82-f17d-4556-8c48-b246b36822b8># 当然在等待10s之后,我们也能通过如下方式获取结果>>> from celery.result import AsyncResult>>> res = AsyncResult("c41bee82-f17d-4556-8c48-b246b36822b8")>>> res.result18执行该异步任务后,我们在 redis 中查看执行的结果。刚开始是空的,等到10s 之后,结果就会写入 redis 中,默认的 key 是 celery-task-meta-[任务id]:[root@server ~]# redis-cli127.0.0.1:6379> get celery-task-meta-c41bee82-f17d-4556-8c48-b246b36822b8(nil)# 10s过后,结果才会出来127.0.0.1:6379> get celery-task-meta-c41bee82-f17d-4556-8c48-b246b36822b8"{\"status\": \"SUCCESS\", \"result\": 18, \"traceback\": null, \"children\": [], \"date_done\": \"2020-05-12T09:51:53.716003\", \"task_id\": \"c41bee82-f17d-4556-8c48-b246b36822b8\"}"有了上面的基础后,我们就可以实现两个简单的工作了。实验1:异步发送邮件。准备好邮件发送代码,放到 async_tasks/utils.py 中。# 代码位置:async_tasks/utils.pyimport smtplibfrom email.mime.text import MIMETextfrom email.header import Header# 发送方邮箱mail_from = '2894577759@qq.com' # 大家可以使用自己的邮箱作为发送邮箱passwd = 'xxxxx' def send_email(subject_text, content='', receivers=['2894577759@qq.com']): send_html = "<html><head></head><body><h3>{}</h3></body></html>".format(content) msg = MIMEText(send_html, 'html', 'utf-8') # 放入邮件主题 msg['Subject'] = subject_text msg['From'] = mail_from try: s = smtplib.SMTP_SSL("smtp.qq.com", 465) # 登录到邮箱 s.login(mail_from, passwd) # 发送邮件:发送方,收件方,要发送的消息 s.sendmail(mail_from, receivers, msg.as_string()) print("发送邮件成功") except s.SMTPException as e: print("发送邮件失败:{},请手工查看生成的巡检报告".format(str(e))) return False finally: s.quit() return Trueif __name__ == "__main__": send_email('Django-Celery测试', "慕课网的朋友们,大家好!")可以直接使用 python 测试,结果如下:准备异步发送邮件的 task:# 代码位置: async_tasks/tasks.pyfrom celery import shared_taskfrom async_tasks.utils import send_emailfrom first_django_app import celery_app@celery_app.taskdef send_email_task(title, content="慕课网的兄弟们,大家好!"): time.sleep(10) return send_email(title, content)准备好视图函数,比较简单,直接使用异步处理即可:# 代码位置:async_tasks/views.pyfrom django.http.response import HttpResponsefrom async_tasks.tasks import send_email_task# Create your views here.def send_email(request, *args, **kwargs): try: # res = send_email_task.apply_async((), countdown=10) res = send_email_task.delay('这是来自django-celery的测试', '慕课网的朋友们,大家好,我是xxx,来自xxx!') except Exception as e: print('异常:{}'.format(str(e))) return HttpResponse('发送邮件成功,请耐心等待')准备好 URLConf 配置,注意我们这里新建了一个 app,所以需要在主入口也要加上 URLConf 配置,此外还需要在该 app 下新建对应的 urls.py 文件并在其中添加相应的映射关系:# 代码位置:first_django_app/urls.py# ...# 所有url入口urlpatterns = [ url('admin/', admin.site.urls), url('hello/', include('hello_app.urls')), # 添加async_tasks应用的映射入口 url('celery/', include('async_tasks.urls')), url('hello_world/', hello_world), path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))]# 代码位置:async_tasks/urls.pyfrom django.urls import pathfrom async_tasks import viewsurlpatterns = [ path('send_email/', views.send_email),]在项目目录下,启动 celery 服务(最好以守护进程方式),这一步非常重要,千万不能漏掉!!(django-manual) [root@server first_django_app]# celery multi start w1 -A first_django_app --concurrency=4 -l info --logfile=/root/test/celerylog.log --pidfile=celerypid.pid(django-manual) [root@server first_django_app]# ps -ef | grep celeryroot 7592 23339 0 23:35 pts/0 00:00:00 grep --color=auto celeryroot 18503 1 0 22:49 ? 00:00:06 /root/.pyenv/versions/3.8.1/envs/django-manual/bin/python3.8 -m celery worker -A first_django_app --concurrency=4 -l info --logfile=/root/test/celerylog.log --pidfile=celerypid.pid --hostname=w1@serverroot 18851 18503 0 22:49 ? 00:00:00 /root/.pyenv/versions/3.8.1/envs/django-manual/bin/python3.8 -m celery worker -A first_django_app --concurrency=4 -l info --logfile=/root/test/celerylog.log --pidfile=celerypid.pid --hostname=w1@serverroot 18875 18503 0 22:49 ? 00:00:00 /root/.pyenv/versions/3.8.1/envs/django-manual/bin/python3.8 -m celery worker -A first_django_app --concurrency=4 -l info --logfile=/root/test/celerylog.log --pidfile=celerypid.pid --hostname=w1@serverroot 18890 18503 0 22:49 ? 00:00:00 /root/.pyenv/versions/3.8.1/envs/django-manual/bin/python3.8 -m celery worker -A first_django_app --concurrency=4 -l info --logfile=/root/test/celerylog.log --pidfile=celerypid.pid --hostname=w1@serverroot 18903 18503 0 22:49 ? 00:00:00 /root/.pyenv/versions/3.8.1/envs/django-manual/bin/python3.8 -m celery worker -A first_django_app --concurrency=4 -l info --logfile=/root/test/celerylog.log --pidfile=celerypid.pid --hostname=w1@server最后,我们启动服务,然后请求这个异步的接口,效果如下视频所示。可以看到,请求会立马返回,而任务会交给 celery 去执行,并最后将结果放到 redis 服务中。效果演示:26实验2:设置定时任务。我们来在 Django 工程中使用 celery 设置两个定时任务,一个任务用于在某个目录下每隔3秒生成一个日志文件,另一个定时任务则每分钟清除该目录下的所有日志文件。如果想要在 Django 中使用定时任务功能需要靠 beat 完成任务发送功能,当在 Django 中使用定时任务时,需要安装 django-celery-beat 插件。然后在 settings.py 的 INSTALLED_APPS 值中添加 'django_celery_beat' 应用。最后该应用还提供了一些表,我们使用 migrate 命令在我们数据库中迁移这些表,操作如下:(django-manual) [root@server first_django_app]# pip install django-celery-beat...(django-manual) [root@server first_django_app]# python manage.py migrate django_celery_beatOperations to perform: Apply all migrations: django_celery_beatRunning migrations: Applying django_celery_beat.0001_initial... OK Applying django_celery_beat.0002_auto_20161118_0346... OK Applying django_celery_beat.0003_auto_20161209_0049... OK Applying django_celery_beat.0004_auto_20170221_0000... OK Applying django_celery_beat.0005_add_solarschedule_events_choices... OK Applying django_celery_beat.0006_auto_20180322_0932... OK Applying django_celery_beat.0007_auto_20180521_0826... OK Applying django_celery_beat.0008_auto_20180914_1922... OK Applying django_celery_beat.0006_auto_20180210_1226... OK Applying django_celery_beat.0006_periodictask_priority... OK Applying django_celery_beat.0009_periodictask_headers... OK Applying django_celery_beat.0010_auto_20190429_0326... OK Applying django_celery_beat.0011_auto_20190508_0153... OK Applying django_celery_beat.0012_periodictask_expire_seconds... OK来添加两个定时任务,在 settings.py 文件中:# 代码位置:first_django_app/settings.py# ...from celery.schedules import crontabCELERY_BEAT_SCHEDULE = { # 定时任务1:生成日志文件 'task1': { 'task': 'async_tasks.tasks.echo_hello', 'schedule': 3, # 每3秒执行一次 }, # 定时任务2:删除日志文件 'task2': { 'task': 'async_tasks.tasks.clear_logs', 'schedule': crontab(minute='*/1'), 'args': ('/root/test/logs', ) }}首先启动 celery 服务,然后启动celery-beat 服务,这样定时任务就可以看到效果了。(django-manual) [root@server first_django_app]# celery -A first_django_app worker -l info(django-manual) [root@server first_django_app]# celery -A first_django_app beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler就简单这样子,我们就相应于设置了定时任务。我们简单看看演示效果:27由于篇幅限制,就不再看如何在 Django 内置的 admin 管理系统中演示如何添加定时任务了,这个工作就当作课后练习。
- makefile文件编写 欢迎大家学习本课程,希望能帮助大家加深理解
- 在 Windows 上安装 Java 面向就业的最佳首选语言
malloc相关搜索
-
mac osx
machine_start
macox
magellan
malloc
manifest
manifest文件
map
map 遍历
mapreduce编程
maps google com
margin
margin bottom
margin left
margin right
margin top
marginbottom
marginheight
marginleft
margintop