文章目录
- 前言
- 一、常见的动态内存错误
- 1. 对NULL指针的解引用操作
- 2. 对动态开辟空间的越界访问
- 3. 对非动态开辟内存使用free()
- 4. 使用free释放一块动态开辟内存的一部分
- 5. 对同一块动态内存多次释放
- 6. 动态开辟内存忘记释放(内存泄漏)
- 二、几个经典笔试题
- 1.
- 2.
- 3.
- 4.
- 三、 c/c++内存开辟空间图
- 总结
前言
C语言常见的动态内存错误及几个经典笔试题以及c/c++内存开辟空间等的介绍
一、常见的动态内存错误
1. 对NULL指针的解引用操作
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(40);
// 没有对malloc开辟失败的拦截,所以p有可能为空指针
// 程序可能崩溃
*p = 20;
return 0;
}
2. 对动态开辟空间的越界访问
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int* p = (int*)malloc(40);
if (NULL == p)
{
printf("%s\n", strerror(errno));
}
int i = 0;
for (i = 0; i <= 10; i++) // 动态内存越界访问,程序报错
{
*(p + i) = i;
}
free(p);
p = NULL;
return 0;
}
3. 对非动态开辟内存使用free()
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 0;
int* p = &a;
free(p);
p = NULL;
return 0;
}
4. 使用free释放一块动态开辟内存的一部分
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int* p =(int*)malloc(40);
if (NULL == p)
{
printf("%s\n", strerror(errno));
}
int i = 0;
for (i = 0; i < 5; i++)
{
*p = i;
p++; // p 的地址一直在改变,free(p)没有指向动态内存的起始地址
// 程序崩溃
}
free(p);
p = NULL;
return 0;
}
5. 对同一块动态内存多次释放
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int* p = (int*)malloc(40);
// ....
free(p); // 释放了一次,但是p没有置为空指针
// 此时p为野指针
// p = NULL;
// .....
free(p); // 此时程序报错,p是野指针
return 0;
}
6. 动态开辟内存忘记释放(内存泄漏)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void test()
{
int* p = (int*)malloc(40);
if (NULL == p)
{
printf("%s\n", strerror(errno));
return;
}
int flag = 0;
scanf("%d", &flag);
if (flag == 5)
{
return;
}
free(p);
p = NULL;
}
int main()
{
test();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int* test()
{
int* p = (int*)malloc(40);
if (NULL == p)
{
return p;
}
return p;
}
int main()
{
// test 函数开辟空间
int* ret = test();
// 忘记释放
return 0;
}
所以,动态开辟的空间一定要释放,并且要正确释放。
二、几个经典笔试题
1.
char* str = "hello world";
printf(“%s\n”, str); // hello world
printf(“hello world”\n); // hello world
printf(str) // hello world
str 存放 h 的地址, 所以 printf(""hello world); 和 printf(str);是一样的效果
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void GetMemory(char* p)
{
p = (char*)malloc(100);
// 出了GetMemory函数 p会被销毁
// 无法再找到 动态内存,所以内存泄漏
}
void Test(void)
{
char* str = NULL;
GetMemory(str);
// str 是空指针,解引用时,程序崩溃
strcpy(str, "hello world");
printf(str);
}
int main()
{
Test();
return 0;
}
- 修改1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void GetMemory(char** p)
{
*p = (char*)malloc(100);
// *p 指向str,str被赋值为动态内存的地址
}
void Test(void)
{
char* str = NULL;
GetMemory(&str);
strcpy(str, "hello world"); // hello world
printf(str);
free(str);
str = NULL;
}
int main()
{
Test();
return 0;
}
- 修改2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* GetMemory()
{
char* p = (char*)malloc(100);
// *p 指向str,str被赋值为动态内存的地址
return p;
}
void Test(void)
{
char* str = NULL;
str = GetMemory();
strcpy(str, "hello world"); // hello world
printf(str);
free(str);
str = NULL;
}
int main()
{
Test();
return 0;
}
2.
#include <stdio.h>
#include <string.h>
char* GetMemory(void)
{
char p[] = "hello world";
return p; // 出了 函数 ,p[] 就会被销毁
// 所以str 接收到了地址,但是p[]的内容被销毁, 无法被找到
}
void Test(void)
{
char* str = NULL;
str = GetMemory(); // str 是一个野指针
printf(str); // 烫烫烫烫烫烫烫烫x魪?
}
int main()
{
Test();
return 0;
}
3.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* GetMemory(char** p, int num)
{
*p = (char*)malloc(num);
}
void Test(void)
{
char* str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str); // hello
// 但是没有释放内存空间
// 可以如下释放
/*free(str);
str = NULL;*/
}
int main()
{
Test();
return 0;
}
4.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void Test(void)
{
char* str = (char*)malloc(100);
strcpy(str, "hello");
free(str); // 释放空间,str变成野指针
if (str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
int main()
{
Test();
return 0;
}
三、 c/c++内存开辟空间图
总结
C语言常见的动态内存错误及几个经典笔试题以及c/c++内存开辟空间等的介绍