)
1.为什么要有动态内存分配我们已经掌握的内存开辟方式有但是上述的开辟空间的方式有两个特点·空间开辟大小是固定的·数组空间一旦确定了大小不能调整但是有时候我们需要的空间大小在程序运行的时候才能知道那么上述两种方式便不能满足我们的需求了。而动态内存开辟让我们可以自己申请和释放空间就比较灵活了2.malloc和freemalloc和free都声明在stdlib.h头文件中。2.1malloc函数原型void* malloc(size_t size);功能向内存的堆区申请一块连续可用的空间并且返回这块空间的起始地址。参数size要分配的内存块的字节数返回值·如果开辟成功则返回这块空间的起始地址。·开辟失败返回NULL因此malloc的返回值一定要做检查。·返回值的类型是void*所以malloc函数并不知道开辟空间的类型具体在使用的时候由使用者自己来决定。·如果参数size为0malloc的行为标准是未定义的取决于编译器。2.2free函数原型void* free(void*ptr)功能释放之前通过动态内存分配函数申请的空间参数ptr:指向要释放的内存块的指针·如果参数ptr指向的内存不是动态开辟的那free函数的行为是未定义的·如果ptr是NULL指针则函数什么事都不做但是注意free只是把使用权限还给操作系统但p中还保存着这个地址所以必须要置空避免后续变成野指针。3.calloc和realloc3.1calloc函数原型void* calloc(size_t numsize_t size)功能为num个大小为size的元素开辟一块空间并且把空间的每个字节初始化为0。与malloc的区别calloc会在返回地址之前把申请的空间的每个字节初始化为全0。3.2realloc函数原型void* realloc(void* ptr,size_t size)功能可以调整动态开辟内存的大小。参数ptr:要调整的内存地址size:调整之后的新大小单位是字节返回值·成功返回一个重新分配内存块的void*类型的指针这个指针可能跟原来的指针不同。·失败返回NULL并且原来的内存块保持不变注意·返回值为调整之后的内存起始位置·这个函数会在调整原内存空间大小的基础上将原来内存中的数据移动到新的空间。·realloc在调整内存空间时存在两种情况情况1原有空间之后有足够大的空间最终返回的地址还是旧地址情况2原有空间之后没有足够大的空间会在内存堆区寻找新的满足要求的空间返回新空间的起始地址在这个过程中会发生·寻找新的满足要求的空间·将旧空间的数据拷贝到新空间保证数据不会丢失·释放旧空间返回新空间的起始地址情况3分配失败返回NULL。所以注意下面的写法中用p去接收realloc的返回值就是有问题的万一分配失败p被置空前面二十个字节的数据也就丢失了4.常见的动态内存的错误4.1对NULL指针的解引用操作不做判断直接使用malloc如果返回失败那么就会出现对NULL的解引用操作。4.2对动态开辟空间的越界访问动态开辟的空间也是有自己的内存边界的不能越界访问。4.3对非动态开辟的内存使用free释放如下图如果错误的对arr这个静态内存释放会报错4.4使用free释放一块动态开辟内存的一部分上述代码中的p会使p不再指向动态内存的起始位置所以最后的free只是释放了一部分的p运行时也会报错。4.5对同一块动态内存多次释放4.6动态开辟内存忘记释放内存泄漏