linux系统编程-内存管理day04-选择合适的内存分配机制&存储器操作

  • 本节包含了对合适的内存分配机制的选择,以及常见的存储器操作

选择一个合适的内存分配机制

  • 前面学习了很多内存分配的方式,可能会使我们不知道在一个具体问题中不知道该选择哪一种。(大部分情况下malloc( )总是最好的选择,然而在某些情况下,采用其它的方式会更好一些).
静态分配 和 自动分配

有两类是不需要程序员去控制内存分配的:

  • 中分配临时变量
  • 中分配全局变量
需要程序员控制分配和释放的内存分配方法
  1. malloc( )
  • 优点:简单,方便,最常用
  • 缺点:返回的内存并非用0进行初始化了,只是一段不确定内容的空间,程序员如果想当然的以为是用全0初始化的,则会出问题
  • 用法: char *p = malloc(size);

  1. calloc( )
  • 优点:使数组分配变得容易,用0初始化了内存
  • 缺点:在分配非数组空间时显得较复杂
  • 用法:int * y = calloc(50, sizeof(int));

  1. realloc( )
  • 优点:调整已分配的空间大小
  • 缺点:只能用来调整已分配空间的大小
  • 用法:r = realloc(p, sizeof(struct map));

  1. brk( ) 和 sbrk( )
  • 优点:允许对堆进行深入控制
  • 缺点:对大多数使用者来说过于底层
  • 用法:brk( )会设置数据段的中断点,sbrk( )将数据段末端增加或减少n个字节,其中sbrk(0)返回的是现在断点的地址.

  1. 匿名内存映射
  • 优点:使用简单,可共享,允许开发者调整保护等级并提供建议,适合大空间的分配
  • 缺点:不适合小分配。最优时malloc( )会自动使用匿名内存映射(default情况下,128KB是临界点,临界点可以通过mallopt()来调整在这个临界点)
  • 用法:void p = mmap(NULL, 5121024, PROT_READ|PROT_WRITE, MAP_ANONYMOUS| MAP_PRIVATE, -1, 0);

  1. posix_memalign( )
  • 优点:分配的内存按照任何合理的大小进行对齐
  • 缺点:相对较新,因此可移植性是一个问题;对于对齐的要求不是很迫切的时候,则没有必要使用
  • 用法:
    /* 分配1KB,以256字节对齐 */
    char *buf;
    int ret = posix_memalign(&buf, 256, 1024);

  1. memalign( ) 和 valloc( )
  • 优点:相比posix_memalign( )在其它的Unix系统上更常见
  • 缺点:不是POSIX标准,对齐的控制能力不如posix_memalign( )

  1. alloca( )
  • 优点:最快的分配方式,不需要知道确切的大小,对于小的分配非常适合
  • 缺点:不能返回错误信息,不适合大分配,在一些Unix系统上表现不好
  • 用法:用法与malloc( )一样,但不用自己释放空间. char *p = alloca(1024);

  1. 变长数组VLAs
  • 优点:与alloca( )类似,但在退出此层循环时释放空间,而不是函数返回时
  • 缺点:只能用来分配数组,在一些情况下alloca( )的释放方式更加适用,在其它Unix系统中没有alloca( )常见
  • 用法:
    for (i = 0; i < n; ++i)
    char foo[i + 1];

  • 以上就是对内存分配几种方法的总结,总的来说,malloc( )仍然是最简单最直观的方法,然而有些内存方法,例如基于栈的分配,在linux下能有很好的性能;不过同时,考虑到可移植性问题,要谨慎运用
    ^ ^

存储器操作

C语言提供了很多函数进行内存操作。这些函数的功能和字符串操作函数(如strcmp( ) 以及 strcpy( ))类似,但是他们处理的对象是用户提供的内存区域而不是以NULL结尾的字符串。

  • 注意:这些函数都不会返回错误信息。
  1. 字节设置 memset( ):
#include <string.h>
void *memset(void *s, int c, size_t n);
  • 调用memset( )将把从s指向区域开始的n个字节设置为c
  • 它经常被用来将一块内存清零:
/* zero out [s, s+256) */
memset(s, '\0', 256);
  • 注:如果你可以使用calloc( )分配内存,那就坚决不要使用memset( )了。因为calloc( )可直接从内存中获取已经清零了的内存,这显然比手工的将每个字节清零要高效。

2.字节比较 memcmp( ):

#include <string.h>
int memcmp(const void *s1, const void *s2, size_t n);

和strcmp( )相似,memcmp( )比较两块内存是否相等。

  • 调用memcmp( )比较s1和s2的头n个字节,如果两块内存相同就返回0,如果s1小于s2就返回一个小于0的数,反之则返回大于0的数。
  • 注意:因为结构体填充的存在,通过memcmp( )来比较两个结构是否相等是不可靠的。如果要比较两个结构体,只能一个个比较结构体中的每一个元素
  1. 字节移动
    3.1 memmove( ):
#include <string.h>
void *memmove(void *dst, void *src, size_t n);

memmove( )复制src的前n字节到dst,返回dst。

  • memmove( )可以安全地处理内存区域重叠问题(就是说,dst的一部分在src里面),例如它们允许内存块在一个给定的区域内向上或下移动。

3.1 不支持内存区域覆盖的memcpy( ):

#include <string.h>
void *memcpy(void *dst, const void *src, size_t n);
  • 除了dst和src间不能重叠,这个函数基本和memmove( )一样。如果重叠了,函数的结果是未被定义的。

3.2 memccpy( ):

  • 一个安全的复制函数
#include <string.h>
void *memccpy(void *dst, const void *src, int c, size_t n);

memccpy( )和memcpy( )类似,但当它发现字节c在src指向的前n个字节中时会停止拷贝。它返回指向dst中c后一个字节的指针,或者当没有找到c时返回NULL。

3.3 mempcpy( ):

  • 可以使用mempcpy( )来跨过拷贝的内存
#define _GNU_SOURCE
#include <string.h>
void *mempcpy(void *dst, const void *src, size_t n);
  • mempcpy( )和memcpy( )几乎一样,区别在于mempcpy( )返回的是指向被复制的内存的最后一个字节的下一个字节的指针。
  • 当在内存中有连续的一系列数据需要拷贝时它是很有用的,但是它并没有太大的性能提升,因为返回的指针只是dst+n而已。
  • 这个函数是GNU中特有的
  1. 字节搜索
    4.1 memchr( ):
#include <string.h>
void *memchr(const void *s, int c, size_t n);
  • memchr( )从s指向的区域开的n个字节中寻找c,c将被转换为unsigned char.
  • 函数返回指向第一个匹配c的字节的指针,如果没找到c则返回NULL.

4.2 memrchr( ):

#define _GNU_SOURCE
#include <string.h>
void *memrchr(const void *s, int c, size_t n);
  • memrchr( )与memchr( )类似,不过它是从s指向的内存开始反向搜索n个字节,多的字母r代表reverse的意思
  • memrchr( )是GNU的扩展函数,而不是C语言的一部分

4.3 memmem( ):

#define _GNU_SOURCE
#include <string.h>
void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);
  • memmem( )函数在指向长为haystacklen的内存块haystack中查找,并返回第一块和长为needlelen的needle匹配的子块的指针。如果找不到,会返回NULL。
  • 这个函数同样是GNU的扩展函数.
  1. 字节加密
    Linux的C库提供了进行简单数据加密的接口:
#define _GNU_SOURCE
#include <string.h>
void *memfrob(void *s, size_t n);
  • memfrob( )函数将s指向的位置开始的n个字节,每个都与42进行异或操作来对数据进行加密。函数返回s。
  • 再次对相同的区域调用memfrob( )可以将其转换回来
  • 用法:memfrob(secret, len);
  • 这个函数用于对数据加密绝对不适合!它仅限于对于字符串的简单处理.
  • 它是GNU标准函数.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,198评论 6 514
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,334评论 3 398
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,643评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,495评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,502评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,156评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,743评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,659评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,200评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,282评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,424评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,107评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,789评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,264评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,390评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,798评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,435评论 2 359

推荐阅读更多精彩内容

  • C语言中内存分配 在任何程序设计环境及语言中,内存管理都十分重要。在目前的计算机系统或嵌入式系统中,内存资源仍然是...
    一生信仰阅读 1,165评论 0 2
  • 最全的iOS面试题及答案 iOS面试小贴士 ———————————————回答好下面的足够了-----------...
    zweic阅读 2,704评论 0 73
  • 最全的iOS面试题及答案 iOS面试小贴士 ———————————————回答好下面的足够了-----------...
    大罗Rnthking阅读 970评论 0 2
  • __block和__weak修饰符的区别其实是挺明显的:1.__block不管是ARC还是MRC模式下都可以使用,...
    LZM轮回阅读 3,327评论 0 6
  • 注意失眠警讯及早治疗恢复自身心灵健康 一早醒来全身无力疲惫不堪,心中懊悔昨晚的失眠和晚睡。脑海里不断想着上班和家里...
    老陈说健康阅读 333评论 0 0