C语言中的内存管理
开始陆续的发一下唐老师视频的笔记吧,顺便带一些正冲哥书的的内容。不能一下都发出来,因为内容发多了自己也受不了,而且发的都是学习视频时候的一些笔记,可能会有一些问题不是很清晰。
先说一下C语言中的内存管理。
1.动态内存分配
①原因:程序运行过程中,很有可能需要一些额外的内存空间。
②动态内存从哪里来,还给谁?
这块是内存是系统专门预留出来的,给程序动态的分配和动态的归还的。
当free函数的参数为空的时候,那么我们的free什么事都不做了。
clloc和realloc的用法见截图:
动态内存是从堆上分配空间的,具体形式以int为例 int *a = (int*)malloc (5*(sizeof(int)))。
2.栈,堆,静态存储区
①没有栈就没有函数,就没有局部变量。函数是依赖于栈的存在而存在的。
这个栈不是数据结构中的栈,是内存栈。
后进先出的原则没有改变。
每一个函数的调用在内存中都会产生活动记录,这个活动记录包括函数的参数和返回地址等等,所以可以说这个活动记录就是在栈上面建立的。
按照老唐的话说,一个栈应该包含的有如下数据
(1)返回地址(子函数ebp在返回ebp的时候应该指向的位置)
(2)old ebp
(3)数据(包含函数中的所有数据)(这也是子函数和子函数esp指向的位置)
栈的增长方式:从栈底一直向上增长。
②因为栈的数据在函数执行结束之后就会被释放了,没有传递到函数的外部,所以产生了程序中的堆。
堆中申请的内存在程序主动释放前一直有效。堆空间就是为了动态内存分配而产生的。
堆空间必须要通过申请才可以得到。
堆管理的方法有很多。老唐讲的链表法很清晰。
③程序静态存储区
程序静态存储区在程序运行的时候就已经开辟出来了,同时在程序运行结束的时候释放。
静态程序区的大小在程序编译的时候就已经规定好了。
程序的静态存储区主要用于保存程序运行的全局变量和静态变量。
这三个存储区是程序中所用的绝大数区域。
3.程序的内存布局。
程序中除了栈,堆,静态存储区以外还有其他的存储区么?
可执行程序的布局:
(1)可执行程序的文件头:操作系统来读这个可执行程序的文件头,看一下这个文件头里的信息是不是系统想要的信息。
(2).text段,这里面保存的是主函数和子函数的运行内容。
(3).data段,这里面保存的是申请并且赋值的全局变量,以及申请并且赋值的静态变量。
(4).bss段,这里面保存的是申请但是没有赋值的全局变量,以及申请并没有赋值的静态变量。
通过上面的四个段,没有找到保存申请并且赋值的局部变量的地方也没有申请但是没有赋值的局部变量的地方。因为局部变量是保存在栈空间中的。
程序文件的布局是程序可执行文件的布局,并不是程序执行过程中的布局,堆栈和静态存储区才是程序执行过程(进程)的布局。
text段、data段和bss段在程序运行的时候(进程)会被映射到进程空间中。
栈和堆是要等到程序运行之后由操作系统进行分配的。
这里的栈可以理解成为一个弹性的东西,所以在程序运行的时候映射过来的段和随着栈的行为来行动。
静态存储区在程序编译的时候就已经开始分配空间了,所以静态存储区在程序运行的时候依然可以对应一部分程序的可执行文件的空间。函数的地址对应的是程序text段中的某个地址。
4.野指针通常是因为指针变量保存的值不是一个合法内存地址造成的。
在C中没有任何手段来判别一个指针是否是野指针。
①局部指针变量没有被初始化。
#include <stdio.h> struct student
{
char *name ;
int no ;
};
int main()
{
struct student s;
//这个strcpy函数是把后面指针变量的内存内容赋给前面指针变量的内容。但是前面的指针变量指向的内存并不确定,所以造成了野指针。
strcpy(s.name,"haha");
s.no = 10;
printf ("%s,%d",s.name,s.no);
}
解决办法:
#include <stdio.h>
#include <string.h>
struct student
{
char *name ;
int no ;
};
int main()
{
struct student s;
s.name = (char*)malloc(sizeof(char)*20);
strcpy(s.name,"haha");
s.no = 10;
printf ("%s,%d",s.name,s.no);
}
上面程序少了一个free(s.name).
②指针释放后程序就归还了这片空间,既然归还了那么就不可以再使用这篇空间了。
使用已经释放后的指针。
例程:
#include <stdio.h>
#include <string.h>
#include <stdlib.h> int f(char*i)
{
printf ("%s\n",i);
free (i);
}
int main()
{
char *p = (char*)malloc(sizeof(char)*5); strcpy(p, "qwertyui"); f(p);
printf ("%s\n",p);
}
解决办法:
#include <stdio.h>
#include <string.h>
#include <stdlib.h> int f(char*i)
{
printf ("%s\n",i);
//free (i);
return 0;
} int main()
{
char *p = (char*)malloc(sizeof(char)*10); strcpy(p, "qwertyui"); f(p); printf ("%s\n",p); free (p); return 0;
}
③指针所指向的变量在指针之前被销毁。
5.内存操作中的经典错误
①非法内存操作
②内存分配成功但是并没有初始化
例程;
#include <stdio.h>
int main()
{
char *p = (char *)malloc(10);
printf(p);
free (p);
return 0;
}
③数组越界
④内存泄露
⑤多次释放指针----谁申请谁释放。
⑥使用已经释放的内存。
6.老唐自己的交通规则
①使用malloc之后应该立刻判断返回值是否为空。可以杜绝操作0地址里面的内容,这个地址是为操作系统使用的。
例程:
#include<stdio.h>
int main()
{
int *p = (int*)malloc(sizeof(int)*5); if (p !== NULL)
{
.....
}
free (p);
return 0;
}
②牢记数组长度,防止越界操作。----使用柔性数组。
③动态申请的操作必须和释放操作相匹配。
④free指针以后,被free的指针要赋值为空。
C语言中的内存管理的更多相关文章
- c 从语言中的内存管理
在C里,内存管理是通过专门的函数来实现.另外,为了兼容各种编程语言,操作系统提供的接口通常是 C 语言写成的函数声明(Windows 本身也由C和汇编语言写成). 1 分配内存 malloc 函数 需 ...
- Cocos2d-x开发中C++内存管理
由于开始并没有介绍C++语言,C++的内存管理当然也没进行任何的说明,为了掌握Cocos2d-x中的内存管理机制,是有必要先了解一些C++内存管理的知识.C++内存管理非常复杂,如果完全地系统地介绍可 ...
- objective-C 中的内存管理解说
初学objectice-C的朋友都有一个困惑,总觉得对objective-C的内存管理机制琢磨不透,程序经常内存泄漏或莫名其妙的崩溃.我在这里总结了自己对objective-C内存管理机制的研究成果和 ...
- JNI中的内存管理(转)
源:JNI中的内存管理 JNI 编程简介 JNI,Java Native Interface,是 native code 的编程接口.JNI 使 Java 代码程序可以与 native code 交互 ...
- javascript中的内存管理和垃圾回收
前面的话 不管什么程序语言,内存生命周期基本是一致的:首先,分配需要的内存:然后,使用分配到的内存:最后,释放其内存.而对于第三个步骤,何时释放内存及释放哪些变量的内存,则需要使用垃圾回收机制.本文将 ...
- Android中的内存管理机制以及正确的使用方式
概述 从操作系统的角度来说,内存就是一块数据存储区域,属于可被操作系统调度的资源.现代多任务(进程)的操作系统中,内存管理尤为重要,操作系统需要为每一个进程合理的分配内存资源,所以可以从两方面来理解操 ...
- C语言之动态内存管理
C语言之动态内存管理 大纲: 储存器原理 为什么存在动态内存的开辟 malloc() free() calloc() realloc() 常见错误 例题 柔性数组 零(上).存储器原理 之前我们提到了 ...
- C语言中动态内存分配的本质是什么?
摘要:C语言中比较重要的就是指针,它可以用来链表操作,谈到链表,很多时候为此分配内存采用动态分配而不是静态分配. 本文分享自华为云社区<[云驻共创]C语言中动态内存分配的本质>,作者: G ...
- windev中的内存机制及其与C语言中的内存指针相似性(一)
windev中的内存机制,是初入windev世界必须要越过的一道高山,以下我的理解和经验未必都对,如有错误或遗漏,以后再纠正或补充!另外,以下内容,咱先谈应用,再说对机制的认识和理解. 一.新建表单, ...
随机推荐
- 《Java并发编程实战》第二章 线程安全 札记
一个.什么是线程安全 编写线程安全的代码 其核心是管理国事访问的操作. 共享,可变的状态的訪问 - 前者表示多个线程訪问, 后者声明周期内发生改变. 线程安全性 核心概念是正确性.某个类的行为与其规范 ...
- matlab练习程序(PCA<SVD>)
clear all;close all;clc;img1=imread('Corner.png');img2=imread('Corner1.png');img3=imread('Corner2.pn ...
- 翻译器DIY它———算在英文文本中的单词数,字符和行数
咳咳.这部分应该是序列化编译器DIY的,然而,在这样做DIY第一次使用前flex 为了练练手,对于后者的理解是有帮助. 在word 我经常看到一个字计数功能,因此,它是如何实现,当然,首先想到的是要经 ...
- Telephone Lines USACO 月赛
以前做过这套题目 这个题又重新写了:http://www.cnblogs.com/jh818012/archive/2013/05/05/3182681.html 还是以前的思路 一直错在一个地方:决 ...
- 《UNIX级别编程环境》注意读出信号(2)
1.功能sigaction sigaction动与指定信号相关联的处理动作.其函数原型例如以下: #inlcude <signal.h> int sigaction(int signo,c ...
- Hadoop之——HBase注意事项
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46447573 1.HBase(NoSQL)的数据模型 1.1 表(table) 存 ...
- c++指针存储应用程序和释放内存的问题
C++中指针在new和delete操作的时候对内存堆都做了些什么呢.下面解: 1.指针的new操作: 指针在new之后,会在内存堆中分配一个空间.而指针中存放的是这个空间的地址.如: void mai ...
- [Error]EOL while scanning string literal
有一个经常性的工作项目.需要一天的一些表数据到外部接口,但最近总是异常.今天检查的原因. 第一本地和测试环境中测试程序是没有问题,有网络环境只会在日志中抛出一个异常.产生主要的例外是推定异常数据. , ...
- Oracle表空间及分区表
(1) 表空间及分区表的概念表空间: 是一个或多个数据文件的集合,所有的数据对象都存放在指定的表空间中,但主要存放的是表, 所以称作表空间.分区表: 当表中的数据量不断增大,查询数据的速度就会变慢,应 ...
- —软测试—(5)计算机系统CPU组成
事实上,我们不得不很早就接触到电脑系统的知识,但仍然会出现不起眼,现象清醒的认识,非常严重丢分. 要我们花功夫去理解,由于非常多东西我们接触不到,比方校验码.码制等.假设你不去理解而是去记,就非常难參 ...