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

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

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

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

静态分配 和 自动分配

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

在栈中分配临时变量

在堆中分配全局变量

需要程序员控制分配和释放的内存分配方法

malloc( )

优点:简单,方便,最常用

缺点:返回的内存并非用0进行初始化了,只是一段不确定内容的空间,程序员如果想当然的以为是用全0初始化的,则会出问题

用法: char *p = malloc(size);

calloc( )

优点:使数组分配变得容易,用0初始化了内存

缺点:在分配非数组空间时显得较复杂

用法:int * y = calloc(50, sizeof(int));

realloc( )

优点:调整已分配的空间大小

缺点:只能用来调整已分配空间的大小

用法:r = realloc(p, sizeof(struct map));

brk( ) 和 sbrk( )

优点:允许对堆进行深入控制

缺点:对大多数使用者来说过于底层

用法:brk( )会设置数据段的中断点,sbrk( )将数据段末端增加或减少n个字节,其中sbrk(0)返回的是现在断点的地址.

匿名内存映射

优点:使用简单,可共享,允许开发者调整保护等级并提供建议,适合大空间的分配

缺点:不适合小分配。最优时malloc( )会自动使用匿名内存映射(default情况下,128KB是临界点,临界点可以通过mallopt()来调整在这个临界点)

用法:void p = mmap(NULL, 5121024, PROT_READ|PROT_WRITE, MAP_ANONYMOUS| MAP_PRIVATE, -1, 0);

posix_memalign( )

优点:分配的内存按照任何合理的大小进行对齐

缺点:相对较新,因此可移植性是一个问题;对于对齐的要求不是很迫切的时候,则没有必要使用

用法:

/* 分配1KB,以256字节对齐 */

char *buf;

int ret = posix_memalign(&buf, 256, 1024);

memalign( ) 和 valloc( )

优点:相比posix_memalign( )在其它的Unix系统上更常见

缺点:不是POSIX标准,对齐的控制能力不如posix_memalign( )

alloca( )

优点:最快的分配方式,不需要知道确切的大小,对于小的分配非常适合

缺点:不能返回错误信息,不适合大分配,在一些Unix系统上表现不好

用法:用法与malloc( )一样,但不用自己释放空间. char *p = alloca(1024);

变长数组VLAs

优点:与alloca( )类似,但在退出此层循环时释放空间,而不是函数返回时

缺点:只能用来分配数组,在一些情况下alloca( )的释放方式更加适用,在其它Unix系统中没有alloca( )常见

用法:

for (i = 0; i < n; ++i)

char foo[i + 1];

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

^ ^

存储器操作

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

注意:这些函数都不会返回错误信息。

字节设置 memset( ):

#include

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

int memcmp(const void *s1, const void *s2, size_t n);

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

调用memcmp( )比较s1和s2的头n个字节,如果两块内存相同就返回0,如果s1小于s2就返回一个小于0的数,反之则返回大于0的数。

注意:因为结构体填充的存在,通过memcmp( )来比较两个结构是否相等是不可靠的。如果要比较两个结构体,只能一个个比较结构体中的每一个元素。

字节移动

3.1 memmove( ):

#include

void *memmove(void *dst, void *src, size_t n);

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

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

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

#include

void *memcpy(void *dst, const void *src, size_t n);

除了dst和src间不能重叠,这个函数基本和memmove( )一样。如果重叠了,函数的结果是未被定义的。

3.2 memccpy( ):

一个安全的复制函数

#include

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

void *mempcpy(void *dst, const void *src, size_t n);

mempcpy( )和memcpy( )几乎一样,区别在于mempcpy( )返回的是指向被复制的内存的最后一个字节的下一个字节的指针。

当在内存中有连续的一系列数据需要拷贝时它是很有用的,但是它并没有太大的性能提升,因为返回的指针只是dst+n而已。

这个函数是GNU中特有的

字节搜索

4.1 memchr( ):

#include

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

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

void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);

memmem( )函数在指向长为haystacklen的内存块haystack中查找,并返回第一块和长为needlelen的needle匹配的子块的指针。如果找不到,会返回NULL。

这个函数同样是GNU的扩展函数.

字节加密

Linux的C库提供了进行简单数据加密的接口:

#define _GNU_SOURCE

#include

void *memfrob(void *s, size_t n);

memfrob( )函数将s指向的位置开始的n个字节,每个都与42进行异或操作来对数据进行加密。函数返回s。

再次对相同的区域调用memfrob( )可以将其转换回来

用法:memfrob(secret, len);

这个函数用于对数据加密绝对不适合!它仅限于对于字符串的简单处理.

它是GNU标准函数.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值