1 常见内存错误
- 结构体成员指针未初始化
- 结构体成员指针未分配足够的内存
- 内存分配成功,但未初始化
- 内存操作越界
我们记得定义一个指针的时候要初始化,却容易忘记定义结构体变量时初始化指针成员。指针未分配足够的内存会导致越界操作的问题。内存分配成功,但未初始化,这个可能回造成字符串方面的错误。内存操作越界可能会操作不因该操作的内存,比如字符串没有结尾的 ‘\0’,复制的时候没有发现结尾的 ‘\0’,导致越界了。第四条包括的 2,3 条。
2 找内存错误
下面我们来找找下面的程序中哪里出现了内存错误呢?
// 42-1.c
#include <stdio.h>
#include <malloc.h>
void test(int* p, int size)
{
int i = 0;
for(i=0; i<size; i++)
{
printf("%d\n", p[i]);
}
free(p);
}
void func(unsigned int size)
{
int* p = (int*)malloc(size * sizeof(int));
int i = 0;
if( size % 2 != 0 )
{
return;
}
for(i=0; i<size; i++)
{
p[i] = i;
printf("%d\n", p[i]);
}
free(p);
}
int main()
{
int* p = (int*)malloc(5 * sizeof(int));
test(p, 5);
free(p);
func(9);
func(10);
return 0;
}
错误1:第 30 行申请的内存在第 11 行和第 32 行释放了两次,会导致程序崩溃。(应该采用在哪里申请就在哪里释放的方法)
错误2:func 函数中,如果 size 值为奇数,则直接返回,申请的内存没有释放,导致内存泄漏。
下面再看一个实例,同样的找出内存操作的错误。
// 41-2.c
#include <stdio.h>
#include <malloc.h>
struct Demo
{
char* p;
};
int main()
{
struct Demo d1;
struct Demo d2;
char i = 0;
for(i='a'; i<'z'; i++)
{
d1.p[i] = 0;
}
d2.p = (char*)calloc(5, sizeof(char));
printf("%s\n", d2.p);
for(i='a'; i<'z'; i++)
{
d2.p[i] = i;
}
free(d2.p);
return 0;
}
错误1:第 10,11 行,定义了结构体变量,但是没有对结构体变量的指针初始化。所以第 15 行在操作野指针。(所以要记得定义变量的时候就要初始化)
错误2:第 17 行申请了 5 个字节的内存,但是第 19 行却操作了大于 5 字节的内存,越界操作了。
3 内存操纵的规则
下面总结一下内存操纵的规则,来减少内存错误。
1、动态内存申请之后,应该立即检查指针值是否为 NULL,防止使用 NULL指针。
2、free 指针之后必须立即赋值为 NULL。
3、任何于内存操作相关的函数都必须带长度信息
4、malloc 操作和 free 操作必须匹配,防止内存泄漏和多次释放。
4 小结
1、内存错误的本质源于指针保存的地址为非法值
- 指针变量未初始化,保存随机值
- 指针运算导致内存越界
2、内存泄漏源于 malloc 和 free 不匹配 - 当 malloc 次数多余 free 是,产生内存泄漏
- 当 malloc 次数少于 free 时,程序可能崩溃
来源:CSDN
作者:-出发-
链接:https://blog.csdn.net/happyjacob/article/details/103773050