malloc_calloc_realloc_void*_NULL指针

目录

malloc:

calloc:

memset

memset函数返回值意义:

memset容易出错的地方:

realloc:

free:

内存泄漏:

内存泄漏原因:

1.丢失内存地址,例如重复给一个指针变量分配内存

2.不使用的内存没有free

悬空指针:

野指针:

void*指针:

NULL:


malloc:

参数指定要分配的字节数,如果成功,返回堆上分配的内存的指针,如果失败,返回NULL;内存不会被修改或清空

函数原型:void* malloc(size_t)

calloc:

在分配的同时清空内存为0,

函数原型:void * calloc(size_t numElements,size_t elementSize);

根据元素个数和每个元素占用内存的乘积分配内存

例如:

int *pi = (int *)calloc(5,sizeof(int));

等价于

int *pi = (int*)malloc(sizeof(int)*5);

memset(pi,0,sizeof(int)*5);

memset

void * memset(void *s,int c,size_t n)

memset会使用某个值填充内存,第一个参数是要填充的起始地址,第二个参数是要填充的内容,第三个参数填充的字节数

calloc可以能malloc慢。

memset函数返回值意义:

刚突然想到一个问题,menset返回值就是第一个参数,它的返回值为什么不设为void,有什么意义了,知道我看了这个例子惨恍然大悟:

char a[200];
strcpy(memset(a, 0, 200), "bla");

memset容易出错的地方:

memset中初始化数据的时候,是逐字节初始化的。例如:想利用memset把一些整型数据初始化为1时,会出bug。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
        int *b=(int *)malloc(sizeof(int)*10);
        memset(b,1,sizeof(int)*10);
        printf("%d\n",b[0]);//16843009
        return 0;
}

 上面结果为16843009,二进制为00000001 00000001 00000001 00000001。它不是把一个int初始为1,而是把每个字节初始化为1。

参考讨论:https://bbs.csdn.net/topics/370127517

那要是填充的内容大于255,岂不是越界了?

realloc:

改变分配的内存的大小

函数原型:void* realloc(void *ptr,size_t size)

返回指向内存块的指针

第一个参数是指向原内存块的指针,第二个是重新分配的内存的大小

如果size比原来分配的内存小,那么多余的内存会还给堆,不能保证多余的内存被清空;

如果比原来分配的大,可能的话,就在紧挨着当前分配的内存后面分配新的内存,否则就在堆得其他区域分配内存,并把旧的内存复制到新区域。

关于重新分配的内存空间比原来内存空间小的问题:

看个例子,

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main(void)
{
        char *string1;
        char *string2;
        string1 = (char*)malloc(16);
        strcpy(string1,"0123456789AB");

        string2 = realloc(string1,8);
        printf("string1 value:%p [%s]\n",string1,string1);
        printf("string2 value:%p [%s]\n",string2,string2);
        return 0;
}

输出结果类似下图:string1还是指向原来的地址,多余的空间的内容没有被修改,还是把原来的内容全部给输出来了。

 但是,调整后只分配了8个字节内存地址,程序实际使用的内存超出分配的内存,不是一个好做法。最简单的方法就是把NUL赋值给地址507。(C语言中没有NUL的宏定义,如果要是用NUL,就自己#define NUL '\0',还是#define NUL ('\0'),不加括号有没有影响?)

free:

free不能从中间释放内存,例如

int *p=(int*)malloc(sizeof(int)*10);

不能free(p+5),从中间释放部分能存;只能free(p)。

内存泄漏:

已经分配的内存以后不再使用时,没有释放,就会造成内存泄漏。内存泄漏可能会导致堆上的内存不够用,严重时,程序就崩了。

内存泄漏原因:

1.丢失内存地址,例如重复给一个指针变量分配内存

2.不使用的内存没有free

自己分配的堆上的内存,没有手动free释放,进程结束后,操作系统会帮我们释放。

全局变量和静态变量是在编译的时候就分配到bss段或数据区的,

初始化静态或者全局变量的时候不能使用函数,例如malloc;注意这里说的是初始化,不是初始化之后的赋值

static int *pi = (int *)malloc(sizeof(int));报错

静态变量在编译的时候就分配的内存,这个时候malloc还不能执行了,改为

static int *pi;

pi = (int *)malloc(sizeof(int))

就可以了。

悬空指针:

int *p = (int*)malloc(sizeof(int)*10);

free(p);

把p所指向的内存释放后,p就成为了一个悬空指针,C语言中指针内存被释放后,指针还是指向原来的地址,但是我们不应该再

使用这块内存了,不然就犯了“释放后使用”错误。

所以一般释放后给指针赋值一个NULL:p=NULL

野指针:

没有初始化的指针,例如int *p;

void*指针:

void *指针具有与char*指针相同的形式和内存对齐方式

任何指针都可以赋值给void*指针,它可以被转换回原来的指针类型。

用void*指针的时候要小心,如果把指针类型转换为void*类型,它可能被转换成不是原来的指针类型。

使用void*函数:

一个最明显的例子,malloc函数的返回类型就是void*,如果不用void*的话,又该用什么返回类型了? int*么,显然不合适。C语言中malloc返回的时候会自动把void*转换成定义的指针类型,但是C++中不会。

NULL:

NULL宏在C中定义为:#define NULL ((void *)0),定义在stddef.h头文件中,ubuntu18.04中stddef.h的路径为

/usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h

NULL被赋值给指针意味着指针不指向任何东西。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值