关于内存地址的个人理解和操作原理
内存寻址的三种模式

内存寻址的三种模型1. 地址的种类首先明确一下逻辑地址和线性地址这两个概念:1. 逻辑地址2. 线性地址3. 物理地址1.1 逻辑地址:逻辑地址是编译器生成的,我们使用在linux环境下,使用C语言指针时,指针的值就是逻辑地址。
对于每个进程而言,他们都有一样的进程地址空间,类似的逻辑地址,甚至很可能相同。
1.2 线性地址:线性地址是由分段机制将逻辑地址转化而来的,如果没有分段机制作用,那么程序的逻辑地址就是线性地址了。
1.3 物理地址物理地址是CPU在地址总线上发出的电平信号,要得到物理地址,必须要将逻辑地址经过分段,分页等机制转化而来。
2. 三种寻址模型x86体系结构下,使用的较多的内存寻址模型主要有三种:1. 实模式扁平模型real mode flat model2. 实模式分段模型real mode segment model3. 保护模式扁平模型protected mode flat model下面是对这三种模型的描述实模式和保护模式相对,实模式运行于20位地址总线,保护模式则启用了32位地址总线,地址使用的是虚拟地址,引入了描述符表;虽然二者都引入了段这样一个概念,但是实模式的段是64KB固定大小,只有16KB个不同的段,CS,DS等存储的是段的序号(想想为什么?)。
保护模式则引入了GDT和LDT段描述符表的数据结构来定义每个段。
扁平模型和分段模型相对,区别在于程序的线性地址是共享一个地址空间还是需要分成多个段,即为多个程序同时运行在同一个CS,DS的范围内还是每个程序都拥有自己的CS,DS:前者(flat)指令的逻辑地址要形成线性地址,不需要切换CS,DS;后者的逻辑地址,必须要经过段选择子去查找段描述符,切换CS,DS,才能形成线性地址。
3. 实模式扁平模型该模式只有在386及更高的处理器中才能出现!80386的实模式,就是指CPU可用的地址线只有20位,能寻址0~1MB的地址空间。
内存存储原理

内存存储原理
内存存储原理是计算机存储系统的重要组成部分。
其主要功能是存储计算机运行时所需要的数据和指令,以便于CPU快速读取和处理。
内存存储原理有以下几个方面:
1. 存储单元:内存存储单元是计算机中存储数据和指令的最小
单位。
每个存储单元都有一个唯一的地址,用于CPU读取和写入数据。
现代计算机中,存储单元通常是字节或字(由几个字节组成)。
2. 存储器结构:内存存储器通常被组织成多个存储单元的数组。
存储器结构的主要参数包括存储单元数量、存储器容量、存取时间、存储器带宽等。
3. 存储器层次结构:为了提高计算机的性能,存储器通常被组
织成多层次结构。
不同层次的存储器具有不同的容量、存取时间和成本等特点。
常见的存储器层次结构包括高速缓存、主存储器和辅助存储器等。
4. 存储器管理:内存存储器的管理包括存储器的分配、回收、
保护、映射等。
为了实现多任务、虚拟内存等功能,存储器管理还需要支持页面交换、内存清除、内存共享等操作。
总之,内存存储原理是计算机存储系统中的关键技术之一。
了解内存存储原理,对于优化计算机性能、提高系统稳定性和安全性等方面都非常重要。
- 1 -。
内存寻址范围

内存寻址范围
嘿,朋友!咱今天来聊聊内存寻址范围这个有点神秘又挺重要的家伙。
你想想,内存就像是一个巨大的仓库,里面存着各种各样的数据,就像仓库里放着各种宝贝。
而内存寻址范围呢,就像是这个仓库的“地图”,告诉你能在多大的区域里找到你想要的宝贝。
比如说,一个小内存,它的寻址范围可能就像一个小房间,能放的东西有限,你能找到的范围也就那么一点点。
可要是一个大内存,那寻址范围就像是一个超级大的库房,广阔得很,能容纳的东西多得让你眼花缭乱。
内存寻址范围的大小,决定了你这台电脑能同时处理多少任务,能运行多大的程序。
要是寻址范围小得可怜,就好像你想盖一座高楼大厦,可给你的地儿就只有巴掌大,那怎么能行?
你看那些大型游戏,画面精美,玩法丰富,需要处理的数据那叫一个多。
要是内存寻址范围不够大,游戏玩到一半,卡了,掉帧了,那多扫兴!
再比如说,专业的设计软件,处理高清图片、复杂的图形,那对内存寻址范围的要求也是高高的。
就像一辆跑车,要在宽阔的赛道上才能尽情驰骋,要是赛道又窄又短,那怎么跑得起来?
现在的科技发展得这么快,各种新的应用、新的技术层出不穷,对内存寻址范围的要求也是越来越高。
这就像是我们的生活,不断追求更大的空间,更舒适的环境。
总之,内存寻址范围可不是个能随便忽视的小角色。
它就像一个默默支撑着整个电脑系统运行的幕后英雄,决定着我们能在电脑世界里走多远,能玩得多尽兴,能工作得多高效。
所以,咱可得重视它,选电脑的时候,多留意留意这方面的参数,别到时候因为内存寻址范围不够,让咱的电脑体验大打折扣,你说是不是这个理儿?。
计算机操作系统内存管理了解内存分配和回收的原理

计算机操作系统内存管理了解内存分配和回收的原理计算机操作系统内存管理是操作系统中极为重要的一部分,它负责管理计算机主存(内存)的分配和回收。
内存分配和回收的原理对于了解计算机系统的运行机制至关重要。
本文将从内存管理的基本概念开始,介绍内存的分配和回收原理。
一、内存管理基本概念内存管理是操作系统中的一个重要功能,其主要任务是将有限的内存资源分配给各个进程,并及时回收不再使用的内存。
内存管理的核心是虚拟内存技术,它将计算机的内存空间划分为若干个固定大小的页或块,每个进程都认为自己拥有整个内存空间。
二、内存分配原理1. 连续分配在早期的操作系统中,内存分配采用的是连续分配原理。
系统将内存分为固定大小的分区,并为每个进程分配连续的内存空间。
这种分配方法简单高效,但会导致内存碎片问题,进而影响系统性能。
2. 非连续分配为解决内存碎片问题,后来的操作系统引入了非连续分配原理。
非连续分配可以分为分页式和分段式两种方式。
- 分页式:将物理内存划分为固定大小的页框,逻辑地址空间也被划分为相同大小的页。
通过页表实现逻辑地址到物理地址的映射。
- 分段式:将逻辑地址空间划分为若干个段,每个段的大小可以不同。
通过段表实现逻辑地址到物理地址的映射。
三、内存回收原理内存回收是指在进程不再使用某块内存时,及时将其释放,使其成为可供其他进程使用的空闲内存。
内存回收涉及到的主要原理有以下几种:1. 清除位图操作系统通过使用一张位图,来记录内存中的空闲块和已分配块的状态。
当一个进程释放内存时,系统会将相应的位图标记为空闲,以便后续进程可以使用。
2. 空闲链表操作系统通过维护一个空闲链表来管理空闲内存块。
当一个进程释放内存时,系统会将该内存块插入空闲链表,使其成为可供其他进程分配的空闲内存。
3. 垃圾回收垃圾回收是指当进程释放内存后,操作系统自动检测并回收无法访问到的对象所占用的内存。
垃圾回收可以通过引用计数和标记清除等算法实现。
四、内存管理策略为了提高内存利用率和系统性能,操作系统采用了一系列内存管理策略:1. 内存分配策略- 最先适应算法:从空闲链表中选择第一个足够大的内存块分配给进程。
0x77932393指令引用的0x02a2e395内存

0x77932393指令引用的0x02a2e395内存全文共四篇示例,供您参考第一篇示例:0x77932393指令引用的0x02a2e395内存在计算机领域中,0x77932393指令引用的0x02a2e395内存是一个重要的概念,它涉及到计算机内存管理、指令执行以及数据处理等多个方面。
本文将从多个角度介绍这一概念,包括其定义、功能、应用、原理等内容,希望能够对读者有所帮助。
需要了解0x77932393指令引用的0x02a2e395内存是什么意思。
在计算机中,所有的指令和数据都是以二进制的形式存储和处理的,每个内存地址都对应着特定的内容。
0x77932393指令是一条特定的指令,用来引用内存中的数据;而0x02a2e395则是内存中的一个地址,代表着特定的数据单元。
当计算机执行0x77932393指令时,它就会根据这个指令中包含的地址0x02a2e395来从内存中读取相应的数据。
这样的设计可以使计算机能够灵活地处理数据和指令,实现各种复杂的计算和操作。
0x77932393指令引用的0x02a2e395内存在计算机的运行过程中扮演着至关重要的角色,它直接影响着计算机的性能和功能。
在实际的应用中,0x77932393指令引用的0x02a2e395内存被广泛地运用在各种计算机系统中。
无论是个人电脑、服务器、嵌入式系统还是超级计算机,都需要依靠这一机制来完成各种任务。
从简单的数据读取到复杂的图形处理,从网络通信到人工智能,都离不开0x77932393指令引用的0x02a2e395内存的支持。
要了解0x77932393指令引用的0x02a2e395内存的原理,需要深入学习计算机体系结构和操作系统原理。
在现代计算机系统中,内存管理是一个重要的话题,涉及到虚拟内存、页面置换、内存保护等多个方面。
这些都是为了使得0x77932393指令引用的0x02a2e395内存能够高效地运行,同时保证系统的稳定性和安全性。
什么是内存地址,如何理解内存和内存地址

什么是内存地址,怎么理解内存地址.
一.了解什么是内存
内存的误解
现在的人们使用手机更多了,在对事物的称呼上其实并不严谨.例如:手机有32/64/128/512GB 的’内存’,这其实是不对的称呼,我们经常讲的6g/8g才是内存或运行内存,而我们口语上说的’内存’其实应该是储存才对.
内存的作用
内存又可以称呼为‘内存储器’或’主存储器’其作用是辅助CPU与外部存储器的沟通和暂时存放CPU的运算数据.
二.什么是内存地址
想象理解
我们可以想象一下,一个完整的内存是由若干个小内存段构成,小内存段依次排序1,2,3,4,5,6……,那么在这样的一个环境里,这些数字1-N每一个都代表一个内存段,我们根据数字的编号就可以找到指定的内存段,这和内存地址的作用是一致的,即内存地址就是对内存的编号.
内存是存储数据的,内存地址是对存储数据的一个标识,指向数据却不是数据,通过内存地址的指引,可以访问到内存当中指向的数据.。
内存寻址原理

内存寻址原理内存寻址原理是计算机中非常重要的一个概念,它是指计算机在进行数据读取和写入时,如何通过内存地址来定位数据的过程。
在计算机中,每个数据都有一个唯一的内存地址,通过这个地址,计算机可以快速地找到并读取或写入数据。
下面我们来详细了解一下内存寻址原理。
我们需要知道计算机内存的组成。
计算机内存由许多存储单元组成,每个存储单元都有一个唯一的地址。
这些存储单元按照一定的规律排列,形成了内存地址空间。
在计算机中,每个存储单元的大小通常是8位或16位,也就是一个字节或两个字节。
当计算机需要读取或写入数据时,它需要知道数据的内存地址。
这个地址通常是由程序员在编写程序时指定的,也可以由操作系统动态分配。
计算机通过总线将地址发送到内存控制器,内存控制器根据地址找到对应的存储单元,并将数据读取或写入到这个存储单元中。
在内存寻址过程中,还需要考虑数据的类型。
不同类型的数据在内存中占用的存储单元数量不同。
例如,一个整数通常占用4个字节,而一个字符只占用1个字节。
因此,在读取或写入数据时,计算机需要知道数据的类型,以确定需要读取或写入多少个存储单元。
内存寻址还需要考虑字节序问题。
字节序指的是数据在内存中存储的顺序。
在计算机中,有两种字节序:大端字节序和小端字节序。
大端字节序是指数据的高位字节存储在低地址,小端字节序是指数据的低位字节存储在低地址。
在读取或写入数据时,计算机需要知道数据的字节序,以正确地读取或写入数据。
内存寻址原理是计算机中非常重要的一个概念,它决定了计算机如何读取和写入数据。
在实际编程中,程序员需要了解内存寻址原理,以确保程序能够正确地读取和写入数据。
同时,操作系统也需要考虑内存寻址原理,以优化内存的使用和管理。
内存地址是什么

内存地址是什么所谓的内存地址,指的就是在计算机系统中或移动智能设备如智能手机中运行内存的位置,在计算机界,我们通常以十六进制的方式表示这个特殊的内存地址,并称之为内存地址编号。
在汇编语言中,内存地址编号经常会被使用。
店铺就在这里给大家详细介绍内存地址。
内存地址的作用既然内存被赋予了内存地址的概念,并使用编号对其进行表示,那么内存地址的作用必然是非常大的。
计算机科学中,我们将在8086模式下对某一个寄存器进行向左移动大约4位的操作,内容被送到内存总线的位置,而地址与ADDR相加同时得到相关的引导,我们就能够一个关于内存单元的物理地址,程序中的这个地址也被称为逻辑地址。
相反,若计算机设备处在80386的保护模式下,相关的内存内容则不会被送至内存的总线位置,而是被送到了内存管理单元,英文简称为MMU,它能够完成内存工作的地址转换,配合计算机完成内存应当完成的操作和工作。
三种不同的地址区分说到内存的地址管理知识,我们就不得不提一提关于内存地址的三种不同形式,它们分别是逻辑地址、线性地址和物理地址,当然这是在80386的模式下。
物理地址:顾名思义,物理地址就是实际中内存的地址和位置,它是最直观的表示方式,物理地址也是一个32位的无符号整数。
物理地址和逻辑地址是计算机科学中最重要的地址表示方式,也是汇编语言中经常涉及到的概念。
逻辑地址:最底层最原始的机器语言会经常使用逻辑地址完成工作。
它独特的寻址方式在目前主流的各个处理器中表现的非常详细具体,Windows程序员能够使用这种寻址方式将程序进行拆分。
而逻辑地址的组成元素则是段和偏移量。
线性地址:线性地址比较特殊,它不同于其他内存地址,而是使用无符号的整数构成的,位数为32位。
线性地址最多能够表达容量达到4GB的内存空间。
当然,为了减少表示的难度和字符长度,在进行对线性地址的表示的时候,我们也一般采用的是十六进制表示方式。
内存地址的相关概念现在都已经说得差不多了,熟悉计算机编程语言的人应该都知道,汇编语言的表示方式和书写格式就是根据寄存器偏移和内存地址的表示进行书写进而实现对计算机的命令和控制的,汇编语言非常直观的体现了计算机内存地址的重要作用。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
最近看见太多人询问内存地址的作用和使用方法,我来做个大概的解释吧内存地址,其实电脑的每个操作都会在内存中先存储,然后经CPU处理后返回内存最终显现出来,而内存里有个内存地址,是为了区分各种不同数据的,而每个地址则相对应一个数据。
网络游戏中,数据也会先存放到内存中,然后进行处理,包括坐标、血量、MANA等,其实所有信息都是在内存中一一存放并等待处理。
处理完毕后结果将会返回原来的地址中(当然也有返回到其他的)。
通过以上的解释,大家可以明白一个道理,其实任何数据都是会下载到本地电脑上然后经过处理后再返回的(至于返回到网络和返回到本地就看数据的重要性了)包括网页的浏览等,任何在你电脑上可以看见的东西必定先存放到本地内存中或硬盘中等待处理后才会显现出来的。
内存和外挂:说到这里当然要给大家举个例子了,就拿网络游戏来说吧。
以前的网络游戏很多数据都是在本地电脑上进行处理和比对的,例如曾经的精灵,它的游戏币是在本地电脑上进行处理的,处理后的结果再返回服务器,这样就导致了当时的刷钱外挂,因为大家可以修改本地电脑上的内存地址中的数值,然后再返回给服务器。
从以上可以知道单机游戏锁血锁蓝是多么简单的事了吧。
因为所有的数据操作都是在本地运行计算的。
当然,还有的外挂是通过改变封包数据来达到效果的。
例如魔兽世界加速外挂,比如我现在人物的坐标是0 0然后按照正常速度走的话下一秒坐标是1 1。
因为魔兽世界是在本地对人物坐标进行处理,如果只是单一的改变本地游戏坐标的位置,或许你在自己电脑上会看见自己一下跑到 3 3的位置了,但实际游戏服务器上的人物还在1 1这个位置,那就毫无意义。
我们可以截取发送坐标的封包,修改我们下一秒跨度的数值,向服务器发送我下一秒会在3 3的位置,这时服务器处理后你的人物就在3 3的位置了。
当然,整个过程只是改变封包内的数据值,并没有向服务器多发送封包,所以有的人说是加速外挂给游戏带来了压力的说法是错误的。
当然,运营商也可以通过检查你的日常数据来判断你是否使用外挂,所以是没有查不出的外挂,只有不愿意查的外挂。
而现在的网络游戏血、经验、等级、金钱等重要数据都是由服务器计算然后返回给客户端(就是我们),而且每次存放血、蓝等信息的内存地址在每次游戏的启动都会变化,在现在来说,修改其数值已经没有任何意义了,因为那只能让你在本地读取的数值不同而已,而真正的数据被存储在了服务器上,你无法修改。
但是我们可以通过读取内存地址中的数值来精确我们脚本的计算。
脚本与读取内存地址:例如我要做一个脚本,需要在血或蓝少于一个具体的值的时候加血加蓝,这时候我们就可以采用内存地址的读取,因为这种做法可以让脚本以最精确的方式去加血加蓝,而不是去看血条蓝条(其实血条蓝条这时候已经根本不重要)。
在按键精灵里有这么一个脚本。
VBSCall ReadMemory(内存地址:整数(16进制),类型:0-字节 1-整数 2-长整数,输出值-所读取的内容:长整型变量)实际应用(中间的内存地址为假设):VBSCall ReadMemory( &H400000,2,xue)这句脚本的意思为,&H400000为读取内存地址400000中数值;2为读取类型,为长整数;xue则把读取出来的数值保存到xue这个变量中去。
如果这个400000的地址是用来储存血量的。
那我们就可以对xue这个变量来进行判断计算。
实际应用如下If xue<500//放入加血的脚本EndIf也就是当血量少于500的时候我们开始加血。
这个500你可以随意改变实际应用2挂机打怪,然后人物回到挂机点(中间的内存地址为假设):vbs dim x,y,a,b//申明变量(其实在按键精灵里不用这么做)VBSCall ReadMemory( &H400000,2,x)//读取地址中的纵坐标保存到xVBSCall ReadMemory( &H800000,2,y)//读取地址中的横坐标保存到yvbs a=100vbs b=100//也就是原始坐标或者是你想定点的坐标if x>a and y>bmoveto 300 500//以上坐标为虚拟,根据游戏不同自己更改,以下放入这个游戏里移动的移动方式的脚本endif//如果两个坐标都大于我们希望保存的地方,我们就开始向另一个方向移动由此我们可以生成if x<a and y<bif x>a and y<bif x<a and y>bif x=a and y=b一共5种不同的处理方法,这样让人物回到原来的点继续开始打怪就可以轻松制作原点挂机的脚本说了那么多,一定会产生一个很大的问题,如何查找游戏内的内存地址。
内存地址的查找我一般用金山游侠例如我要找红,先在自己满血的时候输入上限,然后搜索,这时候会搜索出很多地址,一些是代表你当前的红,和你的上限,还有一些正好是搜索时碰巧一样的。
OK,在结果里再搜索一次,会去掉一些,这样搜索3次基本上结果已经很少了,但还不准确。
现在,你要做的是就是让自己死了,不同游戏可能不同,死的时候血是0,那就去自杀吧(如果掉经验用小号)。
在结果里用0搜索一次。
别以为这样就结束了,这次要让自己不死,那就让自己少点血,我一般采用脱掉加血上限的装备,让自己的血减少。
依照以上方法反复尝试,最后确定一个地址。
地址出现以后别高兴太早,现在很多游戏内存地址是变动的(至少每次开游戏时就变动),所以可能这次管用,到下次还要重新搜索。
以上这些都是我个人的经验之谈,可能有不精确之处,但我想基本上可以解决大部分问题,如果还有不懂的下面跟贴。
PS:这里的人看贴不回的习惯太不好了以下发文观点皆以 "您已经会使用金山游侠、FPE2000、GameMaster等辅助软体来找寻资料"相信不少玩家都经歷过那段记忆体只有 1M 时代,常常為為了挤那1,2k出来跟OS争的你死我,再看看现在的电脑规格...,科技真一日千里 XD~切入我们的主题,找到某游戏的内存位址数值后该怎麼用。
第一先从按精提供的函数来看VBSCall ReadMemory(v1,v2,v3)v1:内存地址:整数(16进制)v2:类型:0-字节 1-整数 2-长整数v3:输出值-所读取的内容:长整型变量我想很多人一开始就算你找到了数值,却卡在这边不知道要输入什麼,包括我第一次使用也遇到这个问题,所以我觉得有必要就这个部份说明一下。
VBSCall ReadMemory(&HFAC8EA,1,HP)上面这行您一定常用&HFAC8EA 是内存地址 , 1 是读取一个整数然再后再存进 HP 变量裡面不管您用过几次,下面这三个参数说明您一定要看完。
-------------------------------------------------------------------------------------------ReadMemory()第一个参数内存地址:整数(16进制)-------------------------------------------------------------------------------------------&HFAC8EA 是什麼东西,為什麼可以代表一个内存地址?来测试一下,在按精脚本输入[Copy to clipboard]CODE:VBSCall MessageBox(a)VBSCall MessageBox(typename(a))结果:第一次显示 16435434第二次显示 Long没错,&HFAC8EA 是一个长整数,&H就是用来将一个10进制的数字转成16进制的表示法,他的反函数是HEX(),按精测试 VBSCall MessageBox(HEX(16435434))会显示FAC8EA。
*因為我没有 ReadMemory() 这个函数的原形,所以我并不知道為什麼说明文件上面写整数(16进位)也许是很早之前的按精版本确实只能使用整数,只是说明文件没改,也许是他确实是传入一个整数,只是我误会他的意思,有时间我会把函数dump出来看看再上来加註,或是总版老大来龙去脉可以说明一下。
不过他是什麼型态无所谓,至少用到现在没有出错过(不过还是有必要瞭解一下),我们只要确定一点a = &HFAC8EA,变量 a 的型态确实是一个长整数!! 就算你把他强制转形,他还是一个长整数。
且看以下。
[Copy to clipboard]CODE:VBSCall MessageBox(typename(a))//强制转形為整数a = CINT(a)VBSCall MessageBox(typename(a))嗯,二次都是显示 Long,这是因為VBS的特性会根据变量内容来决定他是什麼型态如同以下程式[Copy to clipboard]CODE:b = 3VBSCall MessageBox(a + b)得到 8,因為VBS变数宣告的不定型特性,相对VBS也调整了一些运算子的自动转换,这样是好还是不好,好处就是乱乱写也通,坏处就是在脚本裡做判断时很容易出错,因為你不知道他什麼时候偷偷帮你转形,或是你以為他有帮你转形,事实上并没有,下就这段就不能执行了。
[Copy to clipboard]CODE:b = 3VBSCall MessageBox(a + b)这种情况其实常常发生从文字档裡读出使用者界面参数做判断时,有时应该要HP=30自动吃补药,但是没吃,不是按精有问题,而是你的判断式不正确,避免这种情况发生,读取文字档裡的变数出来后一律强制转形一次(一个被变数型态搞到失眠的人留),微软出了一个VBS不知道该说造大眾还是害死一堆入门设计师。
偏主题有点久了,这部份详细请参考拙作(其实是写给我自已看的)。
按键精灵与VBscrīpt 的基础观念(一)/viewth ...(二)/viewth ... &extra=page%3D2-------------------------------------------------------------------------------------------ReadMemory()第二个参数类型:0-字节 1-整数 2-长整数-------------------------------------------------------------------------------------------為什麼我这麼在意变量是整数还是长整数,原因就在这,第二个参数型态直接就影响到输出的结果,字节跟整数跟长整数有什麼不同,最大就差别就在范围值字节 = 1 Byte (-127 ~ 128) 或不带正负号 (0 ~ 255) = 256整数 = 2 Byte (-32,768 ~ 32,767) 或 (0 ~ 65535) = 65536(256 ^ 2) 长整数 = 4 Byte (-2,147,483,648 ~ 2,147,483,647) 或 (0 ~ 4294967296) = 256 ^ 4上面的范围很重要在,超过原本型态的范围就会產生溢位(overflow)的错误。