动态内存函数的介绍
malloc和free
int main()
{
//int a;//4
//char arr[5];//5
//动态内存开辟
int arr[10] = { 0 };
int* p = (int*)malloc(40);//malloc返回类型是void*
int i = 0;
**//assert(p != NULL);**
if (p == NULL)//**防止p是空指针**
{
printf("%s\n", strerror(errno));
}
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
for (i = 0; i < 10; i++)
{
printf("%d\n", *(p + i));**也可以把*(p+i)写成p[i]**
}
**要释放!!!**
**free(p);
p = NULL;****要失忆**
system("pause");
return 0;
}
void*malloc(size_t size)
1.这个函数向内存申请了一块连续可用的空间,并返回指向这块空间的指针。
2.如果开辟成功,返回一个指向开辟好空间的指针。
3.如果开辟失败,返回NULL,所以malloc的返回值一定要做好检查。
4.返回值类型是void,所以在不知道开辟空间类型的话,要进行所需类型的强制类型转换。
5.要注意malloc和free要成对出现*
free 和 malloc要成对出现
calloc
将开辟的内存空间元素置为0
void* calloc(size_t num,size_t size)(size代表字节)
int main()
{
int* p = calloc(10, sizeof(int));
**if (p == NULL)
{
printf("%s]n", strror(errno));
return 0;
}**
for (int i = 0; i < 10; i++)
{
printf("%d\n", p[i]);
}
**free(p);
p = NULL;**
return 0;
}
malloc和calloc的区别(malloc的效率更高一些)
1.使用形式上有差异,参数不一样
2.calloc开辟好空间后全部初始化为0
realloc
voidrealloc(void ptr,size_t size)
ptr是要调整的内存地址
size是调整之后的大小
返回值为调整位置内存的起始位置
这和函数调整原内存空间大小的基础上,还会将原来的内存中存储的数据移动到新的空间
int main()
{
int* p = calloc(10, sizeof(int));
int*ptr = NULL;
if (p == NULL)
{
printf("%s\n", strror(errno));
return 0;
}
for (int i = 0; i < 10; i++)
{
printf("%d\n", p[i]);
}
**//p = realloc(p, 20 * sizeof(int));
//错误,万一开辟失败,就会将原有的p也置为空,导致内存泄漏,需要定义一个新的变量来接收它**
ptr = realloc(p, 20 * sizeof(int));
if (ptr != NULL)
{
p = ptr;
}
**free(p);
p = NULL;**
return 0;
}
错误示范!!!
void test()
{
int*p = (int*)malloc(10);
if (p == NULL)
{
return 0;
}
if (1)
return 0;
**//还没来得及free,就已经return,导致内存泄漏**
free(p);
p = NULL;
}
int main()
{
test();
getchar();
return 0;
}
对NULL指针的解引用操作
void test()
{
int *p = (int*)malloc(INT_MAX);
**//少了判断,动态内存的开辟一定要判断p是否为空指针**
**//if(p == NULL)
//{
// return;
//}**
*p = 20;
free(p);
p = NULL;
}
int main()
{
return 0;
}
对动态开辟空间的越界访问
void test()
{
int i = 0;
int *p = (int *)malloc(10 * sizeof(int));
if (NULL == p)
{
return;
}
for (i = 0; i < 12; i++**)//当i>10的时候就是越界访问了
{**
*(p + i) = i;
}
free(p);
p = NULL;
}
int main()
{
return 0;
}
对非动态开辟内存使用free释放
void test()
{
int a = 0;
int *p = &a;
free(p);/**/释放昏了头,都没有开辟内存不需要free
**}
int main()
{
return;
}
使用free释放一块动态开辟内存的一部分
int main()
{
int i = 0;
int *p = (int*)malloc(40);
if (p == NULL)
{
return;
}
for (i = 0; i < 10; i++)
{
printf("%d", *p++);**//改成*(p+i)
**}
free(p);
p = NULL;
}
对同一块动态内存多次释放
int main()
{
int i = 0;
int *p = (int*)malloc(40);
if (p == NULL)
{
return;
}
for (i = 0; i < 10; i++)
{
printf("%d", *(p+i));
}
free(p);
**//free (p) ;**
p = NULL;
return 0;
}
动态开辟内存忘记释放(内存泄漏)
经典的面试题 nice面试题
**//找出问题**
void GetMemory(char * p)**//改成 * * p**
{
p = (char*)malloc(100);
**//p只是str的临时拷贝,返回时p不存在,将p改为*p
}**
void Test(void)
{
char *str = NULL;
GetMemory(str);**&str,接收它的是***
strcpy(str, "hello world");
printf(str);
**//free(str); 没释放
//str = NULL**;
}**//内存泄漏 程序崩溃 很重要很重要!!!!**
************************************************
char *GetMeomory(void)
{
char p[] = "hello world";
return p;
**//返回的时候空间可能已经变了,在给str传的时候就不是p所指向数组的首地址
//如果要改的话,可以加一个static固定那块空间
}**
void Teat(void)
{
char *str = NULL;
str = GetMeomory();
printf(str);
}
int main()
{
Test();
return 0;
}
**//错误点:返回栈空间的地址**
***********************************************************
int *Test()
{
int a = 10; **//特别重要!!! 面试题**
return &a;
}
int main()
{
int *p = Test();
return 0;
}
**//和上边一样的错误**
**********************************************
int *f2(void)
{
int *ptr;
**//指针ptr没有初始化,是一个存放非法地址的指针**
*ptr = 10;
return ptr;
}
int main()
{
return 0;
}
*******************
void GetMemory(char **p, int num)
{
*p = (char*)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
**//妈耶,没释放,第一遍看的时候没发现,真是猪脑壳**
}
int main()
{
Test();
return 0;
}
***********************************
#include<stdio.h>
#include<string.h>
void Test(void)
{
char *str = (char*)malloc(100);
strcpy(str, "hello");
free(str);
**//str = NULL;释放了这个空间后,这个空间就合法了**
**if (str != NULL)//如果不把str置为空,这个判断就没了意义**
{
strcpy(str, "world");
printf(str);
}
}
int main()
{
Test();
return 0;
}
要掌握上边的题,特别特别重要!!!