【C语言基础】内存布局和作用域

news2024/12/25 15:38:31
  • (꒪ꇴ꒪(꒪ꇴ꒪ ),hello我是祐言
  • 博客主页:C语言基础,Linux基础,软件配置领域博主🌍
  • 快上🚘,一起学习!
  • 送给读者的一句鸡汤🤔:
  • 集中起来的意志可以击穿顽石!
  • 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏

        学习内存布局之前我们先例啊了解一下内存是什么?

        内存(Memory)是计算机系统中用于存储和读取数据的物理设备。它是计算机的重要组成部分,用于存储程序代码、数据和临时计算结果。

        在计算机中,内存被划分为一系列的存储单元,每个存储单元都有一个唯一地址。每个存储单元可以存储固定大小的数据,例如字节或字(根据计算机的体系结构而定)。这些存储单元按照地址顺序排列,形成了连续的内存空间。

        内存主要作用提供临时存储和快速访问数据的能力,它具有以下特点:

        (1)随机访问:内存中的任何存储单元都可以通过其唯一的地址直接访问,而不需要按顺序逐个访问。
        (2)快速读写:相比于其他存储介质(如硬盘或固态硬盘),内存的读写速度非常快,能够满足计算机系统对实时数据处理的需求。
        (3)临时存储:内存通常用于存储程序的执行代码、运行时数据和临时计算结果。它提供了临时存储的能力,数据在计算完成后可以被清除或替换。
        (4)容量有限:相对于硬盘等外部存储介质,内存的容量通常较小。这意味着需要合理管理内存资源,避免占用过多的内存导致系统性能下降。
        计算机中的内存被分为多个层次,从高速缓存(Cache)到主存(RAM),再到辅助存储器(如硬盘)。不同层次的内存具有不同的访问速度和容量特点,用于满足不同的存储需求。

        在编程中,我们可以使用编程语言提供的内存管理机制来分配和释放内存。例如,动态内存分配函数(如malloc和free)可以在运行时动态地分配和释放内存空间。学习内存和理解内存的概念和管理方式对于编写高效的程序非常重要,主要体现在:合理利用内存资源避免内存泄漏内存溢出等问题。

一、内存布局

        任何一个程序,正常运行都需要内存资源,用来存放诸如变量、常量、函数代码等。这些不同的内容,所存储的内存区域是不同的,且不同的区域有不同的特性。因比我们需要研究财经处内存布局,逐个了解不同内存区域的特性

1.虚拟内存

        每个C语言进程都拥有一片结构相同的虚拟内存,所谓的虚拟内存(VM),就是从实际物理内存(PM)中映射出来的地址规范范围,最重要的特征是所有的虚拟内存布局都是相同的,极大地方便内核管理不同的进程。例如三个完全不相干的进程p1、p2、p3,它们很显然会占据不同区段的物理内存,但经过系统的变换和映射,它们的虚拟内存的布局是完全一样的。

        将其中一个C语言进程的虚拟内存放大来看,会发现其内部包下区域:

  • 代码段(Text Segment):用于存放程序的机器指令,也称为可执行代码。
  • 数据段(Data Segment):用于存放已初始化的全局变量和静态变量。
  • BSS段(Block Started by Symbol):用于存放未初始化的全局变量和静态变量,通常初始化为零。
  • 堆(Heap):用于动态分配内存,主要用于存放程序运行时动态创建的数据结构。
  • 栈(Stack):用于存放函数的局部变量、函数的参数、函数调用的上下文等,由系统自动分配和管理。

        

        内存布局的设计旨在使不同类型的数据在内存中有序地存储,并提供有效的内存管理机制。不同的编程语言和操作系统可能具有不同的内存布局方式,但通常遵循类似的原则和结构。

 

 栈内存

堆内存 

 数据段与代码段

2.内存泄露与内存溢出

        (1)内存泄露(Memory Leak)

        内存泄漏指的是在程序中动态分配的内存没有被正确释放,导致这部分内存无法再被程序使用,从而造成内存资源的浪费。如果内存泄漏问题在程序中反复发生,最终可能会导致程序耗尽可用内存而崩溃。

        以下是一个内存泄漏的示例代码:

void memoryLeak() {
    int *ptr = malloc(sizeof(int));  // 分配内存
    // 没有释放内存,导致内存泄漏
}

        在上述代码中,通过 malloc 函数分配了一块动态内存,但在函数结束时没有调用 free 函数释放内存。这导致每次调用 memoryLeak 函数时都会发生内存泄漏。

        (2)内存溢出(Memory Overflow)

        内存溢出指的是程序试图访问超出其分配内存范围的内存区域。这可能导致程序崩溃、数据损坏或安全漏洞。

        以下是一个内存溢出的示例代码:

void memoryOverflow() {
    int array[5];  // 声明一个包含 5 个整数的数组
    array[5] = 10;  // 超出数组边界,访问无效的内存
}

        在上述代码中,声明了一个包含 5 个整数的数组 array,但在访问第 6 个元素时超出了数组的边界。这将导致访问无效的内存位置,可能引发未定义行为。

        因此,为了避免内存泄漏和内存溢出问题,应该注意以下几点:

  • 在分配内存后,确保在不再使用时及时释放内存,使用 free 函数。
  • 注意数组和指针的边界,避免超出其范围访问内存。
  • 避免无限循环或递归,导致堆栈溢出。
  • 使用内存分配和释放的最佳实践,遵循动态内存管理规则。

 二、作用域


        作用域指的是变量或标识符在程序中的可见性和可访问性范围。作用域规定了在程序的哪些部分可以引用变量或标识符。常见的作用域包括以下几种:

1.全局作用域

        全局作用域中定义的变量可以在整个程序中访问,包括不同的函数和文件。在程序开始时创建,在程序结束时销毁。

#include <stdio.h>

// 未初始化全局变量
// 全局变量就是在花括号之外
// 声明周期是整个程序
// 作用域范围:整个程序
int a;	//.bss
int b[100];

int c;	//声明

// 未初始化,编译的时候不会分配内存
// 初始化,编译时会分配内存
int big_array[10000] = {324, 235, 36};

int main(void)
{

    return 0;
}
     
2.局部作用域

        局部作用域中定义的变量只能在所在的代码块(如函数、循环、条件语句等)中访问。在进入代码块时创建,在离开代码块时销毁。

#include <stdio.h>
 
int main(int argc, char *argv[])
{
	// 在花括号之内定义的变量,就是局部变量
	// 作用域就在这对花括号之间
	// 生存周期,从定义开始,到右花括号结束
	int a = 100;
	
	// 局部变量没有初始化,就是随机值
	int c[100];
	for(int i=0; i<100; i++)
	{
		printf("%d\n", c[i]);
	}
	
	int *pa = &a;	//pa也是局部变量(指针变量)
	
	{
		int b = 200;
		printf("%d\n", b);
	}
	
	
	return 0;
}

3.函数参数作用域

        函数参数的作用域仅限于函数内部。参数在函数调用时被创建,在函数执行完毕后被销毁。
        作用域规定了变量的可见范围和生命周期。不同作用域的变量可以具有相同的名称,但它们是相互独立的,并且在不同的作用域中可以引用不同的内存位置。

#include <stdio.h>
#include <stdlib.h>


int g_a; //.bss   生存周期是整个程序
int g_b = 123;	// .data 生存周期,整个程序

void f(void)
{
	static int n = 1;
}

 
int main(int argc, char *argv[])
{
	// static修饰的局部变量,生存周期为整个程序
	// 默认只初始化一次
	static int c = 45;	// .data 
	
	
	// 堆内存的声明周期,从分配开始,到用自定义释放
	int *p = malloc(12);	// 申请堆内存
	
	
	int a;	// 局部变量,到当前的范围结束,就释放
  
	return 0;
}
4.static关键字

       static 关键字,具有多种用法和含义。它可以用于修饰变量、函数和成员,具体含义取决于上下文。主要作用是限制变量、函数或成员的作用域、链接属性和生命周期。

#include <stdio.h>

// 函数声明
void function();

// 全局变量
static int globalVariable = 10;

int main() {
    // 局部变量
    static int localVariable = 20;
    
    printf("Global variable: %d\n", globalVariable);
    printf("Local variable: %d\n", localVariable);
    
    function();
    
    return 0;
}

// 函数定义
void function() {
    // 局部静态变量
    static int staticVariable = 30;
    
    printf("Static variable in function: %d\n", staticVariable);
}

📢写在最后

  • 今天的分享就到这啦~
  • 觉得博主写的还不错的烦劳 一键三连喔~
  • 🎉感谢关注

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/741073.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UnityVR--机械臂场景10-简单流水线应用2

目录 一. 前言 二. 事件中心修改 三. 机械臂加入DoTween的运动 四. 机械臂关节的控制 一. 前言 上一篇已经完成了流水线的搭建&#xff0c;本篇要完成的是&#xff1a;1. 事件中心的修改&#xff1b;2. 机械臂的DoTween运动改造&#xff1b; 本篇是在事件中心2和机械臂场景…

macOS Ventura 13.5beta5(22G5072a)发布

系统介绍 黑果魏叔 7 月 11 日消息&#xff0c;苹果今日向 Mac 电脑用户推送了 macOS 13.5 开发者预览版 Beta 5 更新&#xff08;内部版本号&#xff1a;22G5072a&#xff09;&#xff0c;本次更新距离上次发布隔了 12 天。 macOS Ventura 带来了台前调度、连续互通相机、Fa…

Python自动化办公:提升效率,释放潜力(借助AI实现)

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。搜…

解密混沌工程——混沌工程实践

随着近两年的数字化转型需求激增&#xff0c;混沌工程这门新兴学科在证券业、银行业备受青睐。尽管混沌工程诞生至今已经有十余年&#xff0c;但对大部分公司的研发团队而言&#xff0c;它仍是一个比较陌生的领域。 混沌工程该如何实施&#xff1f; 上一期我们说到&#xff0c…

Spring Event事件用法 Spring Boot Event事件发布和订阅 Spring Event事件发布 Spring Event事件订阅

Spring Event事件用法 Spring Boot Event事件发布和监听 Spring Event事件发布 Spring Event事件订阅 一、概述 在Spring中可以使用 Spring Event 事件机制&#xff0c;实现功能解耦合。 本文 主要讲解 Spring Event的用法 &#xff0c;至于那些 介绍啊&#xff0c;观察者模式&…

开悟AIArena,深度学习神经网络,暑假开悟比赛的学习

目录 1.赛题简介 1.1.赛题目标 1.2.地图介绍 1.3.规则介绍 2.环境介绍 2.1.观测空间&#xff08;Observation Space&#xff09; 2.1.1.原始数据&#xff1a; 2.1.2.特征数据 2.1.3.特征提取 2.2.动作空间&#xff08;Action Space&#xff09; 2.3.坐标介绍&#xf…

1.MySQL - WindTerm Linux 使用

目录 一、云服务器的使用 二、Linux 和 发行版 三、云服务器的基本操作 四、WindTerm&#xff08;一款 SSH 客户端&#xff09; 4.1 设置 WindTerm 外观 4.2 打开文件管理器 4.3 连接云服务器 4.4 参数 4.5 常见命令 4.5.1 清理屏幕&#xff08;滚屏&#xff09; …

【雕爷学编程】Arduino动手做(158)---VL53L0X激光测距模块2

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

TCP 协议(一)报文结构

TCP 协议&#xff08;一&#xff09;报文结构 TCP 协议&#xff08;二&#xff09;连接与断开 TCP 协议&#xff08;三&#xff09;十种核心机制 TCP 提供面向连接的通信传输&#xff0c;面向连接是指在传送数据之前必须先建立连接&#xff0c;数据传送完成后要释放连接。无论…

从零开始——springboot增删改查小demo

首先&#xff0c;先创建数据库 -----sushe,然后创建表 person&#xff0c;表结构是这样的&#xff0c;一共四个字段。 向里面添加一些寝室成员数据即可。 INSERT INTO person(p_id,p_name,p_phone,p_score)VALUES (1,李阳,123456,7890), (2,张骞,123456,7890), (3,马康敬,1234…

【C语言】指针概要

文章目录 一、什么是指针二、指针类型三、野指针四、二级指针五、字符指针六、数组指针定义数组名 七、函数指针 一、什么是指针 指针就是地址&#xff0c;口语中说的指针通常指的是指针变量。我们可以通过&&#xff08;取地址操作符&#xff09;取出变量的内存起始地址&a…

Nginx转发域名与新增SSL证书校验

1.申请SSL证书 各大资源&#xff1a;SSL免费证书资源 2.我选择的是站点服务 申请成功的界面&#xff1a; 官网安装教程&#xff1a;看看就好系列 3.下载成功后把文件当道nginx中的目录下 4.编写nginx.config配置 增加server配置 通过监听zlXXX.cc域名访问 重定向到https…

C人脸识别

1、原始图片&#xff1a; 2、灰度化下&#xff1a; 3、均值滤波&#xff1a; 4、 二值图加边缘检测 5、生成积分图 6、把待检测的人脸区域划分为25个&#xff0c;因为是一个数组&#xff0c;这样分别统计每个区域的像素个数&#xff1a; x0: 60, y0: 100, x1: 157, y1: 200 …

X86架构上的Linux操作系统安装与配置ARM架构(并进行示例测试/为DDS编译打基础)

1 查看Linux操作系统是运行在X86架构还是ARM架构平台上2 X86和ARM到底是什么关系&#xff1f;3 X86、ARM、Linux三者的关系到底是什么&#xff1f;&#xff08;大白话理解&#xff09;4、在X86架构的Linux操作系统上搭建ARM架构并进行测试&#xff08;看elf文件的类型是否属于a…

Spark---第 1 章 Spark 内核概述

Spark 内核泛指 Spark 的核心运行机制&#xff0c;包括 Spark 核心组件的运行机制、Spark 任务调度机制、Spark 内存管理机制、Spark 核心功能的运行原理等&#xff0c;熟练掌握 Spark 内核原理&#xff0c;能够帮助我们更好地完成 Spark 代码设计&#xff0c;并能够帮助我们准…

HTML5+CSS3小实例:带进度条的人物卡片切换效果

实例:带进度条的人物卡片切换效果 技术栈:HTML+CSS 效果: 源码: 【html】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" conte…

XHcms 1.0代码审计

关于熊海CMS1.0的代码审计&#xff0c;一直想要提升自己的代码审计的能力&#xff0c;php没有继续去深入的学习这门语言&#xff0c;反而直接是审计CMS&#xff0c;就拿着熊海CMS来进行审计。 关于熊海cms的源码&#xff0c;附在下方&#xff1a; 链接&#xff1a;https://pan…

How to Write and Publish a Scientific Paper-Preparing the Tables and Figures

Preparing the Tables and Figures 目录 Preparing the Tables and FiguresWHEN TO USE TABLESHOW TO ARRANGE TABULAR MATERIALEXPONENTS IN TABLE HEADINGSFOLLOWING THE JOURNAL’S INSTRUCTIONSTITLES, FOOTNOTES, AND ABBREVIATIONSADDITIONAL TIPS ON TABLES WHEN TO USE…

algo算法实验平台代码分享

algo算法实验平台代码分享 1. 介绍 本实验平台包括前端及后台两个模块&#xff0c;前端由 vue开发而来&#xff0c;后端主要采用 python编写&#xff0c;主要用于算法效果测试测评及改进。 原平台算法已做脱敏&#xff0c;使用者可以根据自己需求进行改写或开发&#xff0c;此…

Echarts使用,大数据量时,折线图曲线Y轴取值刻度不正确

如下图&#xff0c;当数据量过大时&#xff0c;会出现数值对应Y轴刻度显示不正确问题。 ​​​​​​​ 可检查配置项是否存在sampling字段 option {series: [{data: [...],type: line,smooth: true,symbolSize: 0,sampling: "average", // 注意此行}] }; samplin…