C语言学习笔记--内存操作常见错误
1. 野指针
(1)指针变量中的值是非法的内存地址,进而形成野指针
(2)野指针不是 NULL 指针,是指向不可用内存地址的指针
(3)NULL 指针并无危害,很好判断,也很好调试
(4)C 语言中无法判断一个指针所保存的地址是否合法
2. 野指针的由来
(1)局部指针变量没有被初始化
(2)指针所指向的变量在指针之前被销毁
(3)使用己经释放过的指针
(4)进行了错误的指针运算
(5)进行了错误的强制类型转换
#include <stdio.h>
#include <malloc.h> int main()
{
int* p1 = (int*)malloc(); //这里只分配40字节
int* p2 = (int*); //该地址是非法的,进行了错误的强制转换
int i = ; for(i = ;i < ; i++)
{
*(p1 + i) = - i; //越界访问,p1所指内存总共才40字节,而这里要写入40*4字节
} free(p1); for(i = ; i < ; i++)
{
p1[i] = p2[i]; //p1越界访问,p2非法内存
} return ;
}
3. 基本原则
(1)绝不返回局部变量和局部数组的地址
(2)任何变量在定义后必须用 0 初始化
(3)字符数组必须确认 0 结束符后才能成为字符串
(4)任何使用与内存操作相关的函数必须指定长度信息
#include <stdio.h>
#include <malloc.h>
#include <string.h> struct Student
{
char* name;
int number;
}; char* func()
{
char p[] = "Hello World!";
return p; //返回栈中数组,这是很危险的。
} void del(char* p)
{
printf("%s\n", p);
free(p); //不符谁申请谁释放的原则!
} int main()
{
struct Student s; //危险,结构体应先初始化,因为结构体里有指针!
char* p = func(); //危险,返回局部的数组地址 //strcpy(s.name, p);//s结构体的name指针是野指针! s.number = ;//合法 p = (char*)malloc(); strcpy(p, "Hello World!");//越界,源字符串比目标内存大! del(p); return ;
}
4.常见内存错误
(1)结构体成员指针未初始化
(2)结构体成员指针未分配足够的内存
(3)内存分配成功,但并未初始化
(4)内存操作越界
#include <stdio.h>
#include <malloc.h> void test(int* p, int size) //对内存操作时,有带长度信息
{
int i = ;
for(i = ; i<size; i++)
{
printf("%d\n",p[i]);
} free(p);//不合符谁申请谁释放原则
//当p指向一个数组时,该操作是非法的,因为
//只能free堆中的内存。
} void func(unsigned int size)
{
int* p = (int*)malloc(size * sizeof(int));
int i = ; if(size % != ) //当size为奇数时会p产生内存泄漏
{
return;
} for(i=; i<size; i++)
{
p[i] = i;
printf("%d\n", p[i]);
} free(p); } int main()
{
int* p = (int*)malloc( * sizeof(int)); test(p, ); //test内部释放了p所指内存,不符合谁申请谁释放原则 free(p); //这里重复释放p,会造成程序崩溃 func(); //参数为奇数,会造成内存泄漏!
func();//正常 return ;
}
5.内存操作的交通规则
(1)动态内存申请之后,应该立即检查指针的值是否为 NULL,防止使用 NULL 指针
int* p = (int*)malloc(); if (p != NULL){ //do something here! } ……
(2)free 指针之后必须立即赋值为 NULL。(如 free(p);p=NULL;)
(3)任何与内存操作相头的函数都必须带长度信息!!!!!!!!!
void printf(int* p, int size) //带长度信息size
{ int i = ;
snprintf(buf,sizeof(buf), "%s\n", "Hello World!"); for(i = ;i< size; i++){ //长度信息size
printf("%s\n",p[i])
}
}
(4)malloc 操作和 free 操作必须匹配,防止内存泄露和多次释放。并且遵循谁申请谁释放的原则。
#include <stdio.h>
#include <malloc.h> struct Demo
{
char* p;
}; int main()
{
struct Demo d1;//结构体(内含指针变量)未被初始化
struct Demo d2; char i = ; for(i='a'; i< 'z'; i++)
{
d1.p[i] = i; //d1.p指针未被初始化,内存空间也未分配
} d2.p = (char*)calloc(, sizeof(char)); printf("%s\n", d2.p); for(i='a'; i< 'z'; i++)
{
d2.p[i] = i;
} free(d2.p); return ;
}
内存错误的本质源于指针保存的地址为非法值(如指针未初始化或指针运算导致的越界)。内存泄漏源于malloc和free不匹配。当malloc次数多于free里产生内存泄漏。反之程序可能崩溃。
参考资料:
www.dt4sw.com
http://www.cnblogs.com/5iedu/category/804081.html
C语言学习笔记--内存操作常见错误的更多相关文章
- c语言学习笔记.内存管理.
内存: 每个程序的内存是分区的:堆区.栈区.静态区.代码区. 1.代码区:放置所有的可执行代码,包括main函数. 2.静态区:存放所有的全局变量和静态变量. 3.栈区:栈(stack),先进后出.存 ...
- C语言学习笔记--内存分区
1. 程序中的栈 1.1 栈的简介 (1)栈中现代计算机程序里最为重要的概念之一 (2)栈在程序中用于维护函数调用上下文 (3)函数中的参数和局部变量存储在栈上 (4)栈保存了一个函数调用所需的维护信 ...
- CUBRID学习笔记 7 ms常见错误
基本不是权限问题,就是dll问题. 重新下载或应用dll注意版本. 权限的问题,先本机测试. 看看在web管理有无问题. 剩下的基本就简单了 欢迎转载 ,转载时请保留作者信息.本文版权归本人所有, ...
- c语言学习笔记 - 文件操作
#include <stdio.h>#include <time.h> int main(void){ time_t t; //类似于size_t那 ...
- Python学习笔记: pip install 常见错误汇总
本机环境RHEL8, Python3.9 pip install: 无法安装最新版本的包 在pypi上查看pkg的页面,因为有些pip包的版本对特定的python版本有要求 pip install e ...
- IOS学习笔记48--一些常见的IOS知识点+面试题
IOS学习笔记48--一些常见的IOS知识点+面试题 1.堆和栈什么区别? 答:管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制:对于堆来说,释放工作由程序员控制,容易产生memor ...
- JVM学习笔记——内存结构篇
JVM学习笔记--内存结构篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的内存结构部分 我们会分为以下几部分进行介绍: JVM整体介绍 程序计数器 虚拟机栈 本地方法栈 堆 方法 ...
- Go语言学习笔记九: 指针
Go语言学习笔记九: 指针 指针的概念是当时学C语言时了解的.Go语言的指针感觉与C语言的没啥不同. 指针定义与使用 指针变量是保存内存地址的变量.其他变量保存的是数值,而指针变量保存的是内存地址.这 ...
- Go语言学习笔记(1)——顺序编程
Go语言学习笔记这一堆主要是<Go语言编程>(人民邮电出版社)的读书笔记.中间会穿插一些零碎的点,比如源码学习之类的.大概就是这样吧. 1. 顺序编程 1.1 变量 变量的声明: var ...
随机推荐
- select2 使用
<link href="/plugin/select2/css/select2.min.css" rel="stylesheet" /> <s ...
- 利用闭包特性改写addEventListener的回调函数
var numClicks = 0; document.addEventListener("click",function(){ alert( ++numClicks); },fa ...
- Word 2010 怎么在每一章中使用不同的页眉
1.要做到每一章的页眉不同首先要进行 分节 word2010中 页面布局 -> 分隔符 ->下一页 上述操作即可实现分节 2.实现分节后,在每一节开头的那一页,编辑页眉 ...
- hdu 2087 kmp
http://acm.hdu.edu.cn/showproblem.php?pid=2087 算是模板题吧,找到一个子串之后将模板串指针归零否则会重复计算. #include<bits/stdc ...
- 51nod 1102 单调栈
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1102 1102 面积最大的矩形 基准时间限制:1 秒 空间限制:1310 ...
- Kali 2.0 日常软件
目的 如果你用Kali作为学习安全之类的作业,那么他预装的一些软件已经够用了,但是,如果你打算用它来当做日常主要OS,那么安装一些常用软件就是一项重要作业. 软件 如果你是在标准用户下安装,别忘了su ...
- @angular/cli项目构建--路由2
app.module.ts update const routes: Routes = [ {path: '', redirectTo: '/home', pathMatch: 'full'}, {p ...
- Microsoft Visual Studio 2012 Update 4 RC 3 离线安装程序
Microsoft Visual Studio 2012 Update 4 RC 3 离线安装程序 ☆ 微软官网地址:☆ http://www.microsoft.com/en-us/download ...
- 2017 年比较 Angular、React、Vue 三剑客(转载)
为 web 应用选择 JavaScript 开发框架是一件很费脑筋的事.现如今 Angular 和 React 非常流行,并且最近出现的新贵 VueJS 同样博得了很多人的关注.更重要的是,这只是一些 ...
- 【转】深入剖析Java中的装箱和拆箱
深入剖析Java中的装箱和拆箱 自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西,再来看一下面试笔试中经常遇到的与装箱 ...