线程栈的处理方法及系统技术领域
本发明涉及计算机的线程技术领域,特别是涉及一种线程栈的处理方法及系统。
背景技术
线程技术是计算机软件领域中并发处理业务的核心技术,其与CPU(Central
Processing Unit,中央处理器)硬件直接关联,且所有线程技术的实现原理一致。而维护线
程栈内存又是线程技术的核心点之一,在POSIX Thread(多线程编程)的实现中,线程栈的
内存空间大小通常默认设置或由用户自己设置为一个不容易溢出的大小,但一旦被设置之
后就不允许再被修改。通常情况下,线程栈的内存空间大小不需要很大,能够满足一般的函
数调用就可以满足程序线程的正常运行,但是如果调用比较大的函数时,如:在调用main函
数(主函数)时将会使线程栈的内存空间不够用,此时如果不能及时防止这种情况出现,会
直接导致计算机宕机。
发明内容
基于此,有必要针对传统在调用较大的函数时线程栈的内存空间不够用的问题,
提供一种能够有效避免线程栈溢出的线程栈的处理方法及系统。
为达到发明目的,提供一种线程栈的处理方法,所述处理方法包括:
根据线程调用的调用函数获得所述调用函数对应的函数数据;
将所述函数数据写入线程栈,并获取所述函数数据在写入所述线程栈时在所述线
程栈中的栈顶地址;
判断所述栈顶地址是否位于所述线程栈的栈保护区之内;
如果所述栈顶地址位于所述栈保护区内,则扩展所述线程栈的内存空间,并在扩
展后的线程栈的内存空间中根据所述栈保护区的内存空间大小重新设置所述线程栈的栈
保护区,使所述栈顶地址位于重设的栈保护区之外。
在其中一个实施例中,所述判断所述栈顶地址是否位于所述线程栈的栈保护区之
内的步骤包括:
获取设置在所述栈保护区内的初始魔数数据,并由所述初始魔数数据中提取所述
初始魔数数据的魔数偏移量和魔数占用空间;
根据所述线程栈终止地址和所述魔数偏移量确定所述初始魔数数据的魔数起始
地址,并根据所述魔数起始地址和所述魔数占用空间确定所述初始魔数数据的魔数终止地
址,其中,所述魔数起始地址与所述魔数终止地址界定的区间为所述初始魔数数据的魔数
占用区;
当所述函数数据写入所述线程栈时,获取所述魔数占用区中的当前数据;
将所述当前数据与所述初始魔数数据进行比较,并在所述当前数据与所述初始魔
数数据不一致时,确定所述栈顶地址位于所述栈保护区内。
在其中一个实施例中,所述扩展所述线程栈的内存空间的步骤包括:
根据所述线程栈的当前内存空间将所述线程栈的内存空间扩展为所述当前内存
空间的预设倍数,扩展后的内存空间作为所述线程栈的新内存空间。
在其中一个实施例中,当所述初始魔数数据为多个,每个所述初始魔数数据对应
有不同的魔数偏移量时;所述在扩展后的线程栈的内存空间中根据所述栈保护区的内存空
间大小重新设置所述线程栈的栈保护区,使所述栈顶地址位于重设的栈保护区之外的步骤
包括:
从多个所述初始魔数数据对应的魔数偏移量中获得最大魔数偏移量,并根据所述
最大魔数偏移量和所述魔数占用空间确定所述栈保护区的内存空间大小;
根据所述栈保护区的内存空间大小在所述线程栈的新内存空间中重设所述栈保
护区的起始地址和终止地址,并将所述重设的栈保护区的起始地址作为新的栈保护区起始
地址,将重设的栈保护区的终止地址作为新的线程栈终止地址;
判断所述函数数据在所述线程栈中的所述栈顶地址是否位于所述重设的栈保护
区内,并在所述栈顶地址位于所述重设的栈保护区内时返回所述根据所述初始内存空间将
所述线程栈的内存空间扩展为所述初始内存空间的预设倍数的步骤,直至将所述函数数据
全部写入所述线程栈后所述函数数据的所述栈顶地址位于所述重设的栈保护区之外。
在其中一个实施例中,所述根据所述栈保护区的内存空间大小在所述线程栈的新
内存空间中重设所述栈保护区的起始地址和终止地址,并将所述重设的栈保护区的起始地
址作为新的栈保护区起始地址,将重设的栈保护区的终止地址作为新的线程栈终止地址的
步骤之后,还包括:
将所述新的栈保护区起始地址和所述新的线程栈终止地址保存在相应的存储单
元中,以及
根据初始魔数数据的所述魔数偏移量和所述魔数占用空间在所述重设的栈保护
区内设置新的魔数数据。
在其中一个实施例中,所述扩展所述线程栈的初始内存空间,并根据所述栈保护
区的内存空间大小重新设置所述线程栈的栈保护区,使所述栈顶地址位于重设的栈保护区
之外的步骤之后,还包括:
判断所述调用函数是否结束,并在所述调用函数结束后,删除写入到所述线程栈
中的所述函数数据;
释放所述线程栈扩展的内存空间,保留所述线程栈的初始内存空间;
将所述线程栈的所述初始内存空间对应的所述栈保护区起始地址和所述线程栈
终止地址重新写入相应的存储单元中。
本发明还提供一种线程栈的处理系统,所述处理系统包括:
函数数据获取模块,用于根据线程调用的调用函数获得所述调用函数对应的函数
数据;
栈顶地址获取模块,用于将所述函数数据写入线程栈,并获取所述函数数据在写
入所述线程栈时在所述线程栈中的栈顶地址;
第一判断模块,用于判断所述栈顶地址是否位于所述线程栈的栈保护区之内;
扩展重设模块,用于如果所述栈顶地址位于所述栈保护区内,则扩展所述线程栈
的内存空间,并在扩展后的线程栈的内存空间中根据所述栈保护区的内存空间大小重新设
置所述线程栈的栈保护区,使所述栈顶地址位于重设的栈保护区之外。
在其中一个实施例中,所述第一判断模块包括:
提取单元,用于获取设置在所述栈保护区内的初始魔数数据,并由所述初始魔数
数据中提取所述初始魔数数据的魔数偏移量和魔数占用空间;
第一确定单元,用于根据所述线程栈终止地址和所述魔数偏移量确定所述初始魔
数数据的魔数起始地址,并根据所述魔数起始地址和所述魔数占用空间确定所述初始魔数
数据的魔数终止地址,其中,所述魔数起始地址与所述魔数终止地址界定的区间为所述初
始魔数数据的魔数占用区;
获取单元,用于当所述函数数据写入到所述线程栈后,获取所述魔数占用区中的
当前数据;
比较单元,用于将所述当前数据与所述初始魔数数据进行比较,并在所述当前数
据与所述初始魔数数据不一致时,确定所述栈顶地址位于所述栈保护区内。
在其中一个实施例中,所述扩展重设模块包括:
扩展单元,用于根据所述线程栈的当前内存空间将所述线程栈的内存空间扩展为
所述当前内存空间的预设倍数,扩展后的内存空间作为所述线程栈的新内存空间。
在其中一个实施例中,当所述初始魔数数据为多个,每个所述初始魔数数据对应
有不同的魔数偏移量时,所述扩展重设模块还包括:
第二确定单元,用于从多个所述初始魔数数据对应的魔数偏移量中获得最大魔数
偏移量,并根据所述最大魔数偏移量和所述魔数占用空间确定所述栈保护区的内存空间大
小;
重设单元,用于根据所述栈保护区的内存空间大小在所述线程栈的新内存空间中
重设所述栈保护区的起始地址和终止地址,并将所述重设的栈保护区的起始地址作为新的
栈保护区起始地址,将重设的栈保护区的终止地址作为新的线程栈终止地址;
判断单元,用于判断所述函数数据在所述线程栈中的所述栈顶地址是否位于所述
重设的栈保护区内,并在所述栈顶地址位于所述重设的栈保护区内时返回所述扩展单元,
直至将所述函数数据全部写入所述线程栈后所述函数数据的所述栈顶地址位于所述重设
的栈保护区之外。
在其中一个实施例中,所述扩展重设模块还包括:
保存单元,用于在根据所述栈保护区的内存空间大小在所述线程栈的新内存空间
中重设所述栈保护区的起始地址和终止地址之后,将所述新的栈保护区起始地址和所述新
的线程栈终止地址保存在相应的存储单元中;以及
设置单元,用于根据初始魔数数据的所述魔数偏移量和所述魔数占用空间在所述
重设的栈保护区内设置新的魔数数据。
在其中一个实施例中,所述处理系统还包括:
第二判断模块,用于在扩展所述线程栈的初始内存空间,并根据所述栈保护区的
内存空间大小重新设置所述线程栈的栈保护区,使所述栈顶地址位于重设的栈保护区之外
后,判断所述调用函数是否结束,并在所述调用函数结束后,删除写入到所述线程栈中的所
述函数数据;
释放保留模块,用于释放所述线程栈扩展的内存空间,保留所述线程栈的初始内
存空间;
重写模块,用于将所述线程栈的所述初始内存空间对应的所述栈保护区起始地址
和所述线程栈终止地址重新写入相应的存储单元中。
本发明的有益效果包括:
上述线程栈的处理方法及系统,通过获取调用函数对应的函数数据在线程栈中的
栈顶地址来实时有效地监控函数数据对线程栈的使用情况,通过在线程栈中设置栈保护
区,并在函数数据在线程栈中的栈顶地址位于栈保护区内时,判定线程栈的当前内存空间
即将使用完,从而及时地扩展线程栈的内存空间,以使栈顶地址始终位于栈安全区之内,避
免函数数据溢出线程栈的现象。
附图说明
图1为一个实施例中的设置有栈保护区的线程栈的分布示意图;
图2为一个实施例中的线程栈的处理方法的流程示意图;
图3为一实施例中的图2所示实施例中的步骤S300的流程示意图;
图4为一个实施例中的图2所示实施例中的步骤S400的流程示意图;
图5为另一个实施例中的线程栈的处理方法的流程示意图;
图6为一个实施例中的线程栈的处理系统的结构示意图。
具体实施方式
为了使本发明的目的、技术方案及优点更加清楚明白,以下结合附图及实施例对
本发明线程栈的处理方法及系统进行进一步详细说明。应当理解,此处所描述的具体实施
例仅用以解释本发明,并不用于限定本发明。
在一个实施例中,如图1、图2所示,提供了一种线程栈的处理方法,该方法包括以
下步骤:
S100,根据线程调用的调用函数获得调用函数对应的函数数据。
S200,将函数数据写入线程栈,并获取函数数据在写入线程栈时在线程栈中的栈
顶地址。
S300,判断栈顶地址是否位于线程栈的栈保护区之内。
S400,如果栈顶地址位于栈保护区内,则扩展线程栈的内存空间,并在扩展后的线
程栈的内存空间中根据栈保护区的内存空间大小重新设置线程栈的栈保护区,使栈顶地址
位于重设的栈保护区之外。
本实施例中,当线程调用函数后,会将其调用的调用函数对应的函数数据写入到
该线程对应的线程栈中,即在线程栈中申请一定的存储空间用来存储函数数据,而线程栈
是一种运算受限的线性表,如图1所示,其具有先进后出的特点,即其限制仅允许在表的一
端进行插入和删除运算,这一端称为栈顶,相对地,把另一端称为栈底,而线程栈整体的内
存空间由线程栈起始地址(栈底地址)和线程栈终止地址(栈基地址)界定,当调用函数对应
的函数数据在线程栈的一端写入时,该函数数据在线程栈的写入端的最顶位置即为栈顶地
址,栈顶地址是随着程序的运行而动态变化的,即栈顶地址是随着函数数据的写入而实时
变化的,这样在获得线程栈的栈顶地址后,便可知道函数数据对线程栈的实时使用情况。在
该线程栈中设置栈限制线从而将线程栈划分为栈保护区和栈安全区。在一个实施例中,将
线程栈划分为栈保护区和栈安全区是通过在线程栈中设置魔数数据来实现的,魔数数据是
内核自己定义的,其犹如密码一样不容易出现重复,栈保护区由魔数数据的魔数偏移量及
其自身的魔数占用空间来确定,在首次确定栈保护区之后,栈保护区的内存空间大小将不
会发生变化,即在后续扩展线程栈的内存空间后,并在线程栈的新内存空间中重设的栈保
护区的内存空间大小与首次设置的栈保护区的内存空间大小一致。
由于线程栈具有先进后出的特点,在将函数数据写入线程栈后,便可以获得该函
数数据在线程栈中的栈顶地址,然后判断该栈顶地址是否超出了栈安全区,即栈顶地址是
否位于栈保护区内,如果栈顶地址位于栈保护区,则说明该线程栈的内存空间即将被使用
完,此时为了避免数据溢出线程栈的现象,需要扩展该线程栈的内存空间,并将扩展后的内
存空间作为该线程栈的新内存空间,在该线程栈的新内存空间中重新设置栈保护区,该栈
保护区的设置根据首次设置的栈保护区的内存空间大小来设置,即重设的栈保护区的内存
空间大小与原来的栈保护区的内存空间大小相同,从而使得栈顶地址位于重设的栈保护区
之外。此处需要说明的是,函数数据超出线程栈的线程栈终止地址时,将不存在栈顶地址,
所以,此处的栈顶地址位于重设的栈保护区之外指的是栈顶地址位于扩展后的线程栈的栈
安全区内,从而在调用比较大的函数时也能满足数据对线程栈的需求,不会出现线程栈溢
出的情况,程序能够继续正常执行下去,有效防止计算机的宕机。
本实施例中的线程栈的处理方法,通过获取调用函数对应的函数数据在线程栈中
的栈顶地址来实时有效地监控函数数据对线程栈的使用情况,通过在线程栈中设置栈保护
区,并在函数数据在线程栈中的栈顶地址位于栈保护区内时,判定线程栈的当前内存空间
即将使用完,从而及时地扩展线程栈的内存空间,以使栈顶地址始终位于栈安全区之内,避
免函数数据溢出线程栈的现象。
需要说明的是,该实施例中的调用函数是用来调用主函数的,一般主函数对应的
函数数据比较大,此时需要判断线程栈是否够用。其中,栈保护区为由栈保护区起始地址和
线程栈终止地址界定的内存空间,栈保护区起始地址位于线程栈起始地址和线程栈终止地
址之间。通常,设置栈保护区的内存空间小于线程栈的内存空间,优选地,栈保护区的内存
空间小于线程栈的内存空间的一半。过大的栈保护区将造成线程栈内存空间的资源浪费,
而过小的栈保护区则不能很好起到防止线程栈溢出的作用,因此,通常设置不是很大的内
存空间,例如:200字节的空间内存,来作为栈保护区的内存空间。
在一个实施例中,线程栈的处理方法还包括步骤S400′,如果栈顶地址没有位于栈
保护区内,则将函数数据继续写入线程栈中。当栈顶地址没有位于栈保护区内时,表明栈顶
地址位于栈安全区时,则判定线程栈仍有充足的内存空间供函数数据使用,此时调用函数
继续执行,即该调用函数对应的函数数据继续写入线程栈。
在一个实施例中,参见图3,步骤S300包括:
S310,获取设置在栈保护区内的初始魔数数据,并由初始魔数数据中提取初始魔
数数据的魔数偏移量和魔数占用空间。
S320,根据线程栈终止地址和魔数偏移量确定初始魔数数据的魔数起始地址,并
根据魔数起始地址和魔数占用空间确定初始魔数数据的魔数终止地址。其中,魔数起始地
址与所述魔数终止地址界定的区间为所述初始魔数数据的魔数占用区。
S330,当函数数据写入到所述线程栈时,获取魔数占用区中的当前数据。
S340,将当前数据与初始魔数数据进行比较,并在当前数据与初始魔数数据不一
致时,确定栈顶地址位于栈保护区内。
上述实施例中为判断栈顶地址是否位于栈保护区的一个具体实施方式,在线程栈
中设置栈保护区时,是将线程栈中靠近线程栈终止地址的内存空间的一些字节使用魔数数
据(magic number)来初始化,如果魔数数据只有一个的情况下,该魔数数据所在的位置就
是栈限制线所在的位置,如果魔数数据有多个的情况下,偏离线程栈终止地址最远位置的
魔数数据(即偏移量最大的魔数数据)所在的位置为栈限制线所在的位置。首先获得栈保护
区内的初始魔数数据,并由这些初始魔数数据中提取魔数偏移量和魔数占用空间,由线程
栈终止地址和各个初始魔数数据的魔数偏移量确定各个初始魔数数据的魔数起始地址,再
由魔数起始地址和魔数占用空间确定各个初始魔数数据的魔数终止地址,每个初始魔数数
据所在的内存空间由该初始魔数数据的魔数起始地址和魔数终止地址界定,这里称为魔数
占用区,在函数数据写入线程栈时,获取这些魔数占用区中的当前数据,判断当前数据和初
始魔数数据是否一致,如果一致,说明函数数据还没有写入到初始魔数数据所在的位置处,
即函数数据在线程栈中的栈顶地址还没进入栈保护区,此时线程栈还有充足的内存空间供
函数数据写入,如果不一致,则说明函数数据已写入到初始魔数数据所在的位置处,即函数
数据在线程栈中的栈顶地址已进入栈保护区,此时线程栈即将被用完,需要扩展线程栈的
初始内存空间,以使线程栈有充足的内存空间供函数数据使用。
需要说明的是,当函数数据写入到初始魔数数据所在的魔数占用区时,函数数据
将初始魔数数据覆盖,从而使该魔数占用区内的数据发生变化。
优选地,在一个实施例中,初始魔数数据为多个,每个初始魔数数据对应有不同的
魔数偏移量,即使得多个初始魔数数据分别位于栈保护区的不同位置,这样相当于在栈保
护区内设置了多道栈限制线,使得在第一道栈限制线失效的情况下,第二道栈限制线……
第N道栈限制线也会起作用,从而进一步防止了线程栈溢出的情况发生。进一步地,每个初
始魔数数据的魔数占用空间相同,便于辨识。当然,每个初始魔数数据的占用空间也可不相
同。在一个实施例中,每个初始魔数数据的占用四个字节。
例如:在一个具体的实施例中,初始魔数数据包括第一初始魔数数据STACK_
MAGIC1,第二初始魔数数据STACK_MAGIC2和第三初始魔数数据STACK_MAGIC3,三个初始魔
数数据定义如下:
#define STACK_MAGIC1 0XEACD1532
#define STACK_MAGIC2 0XD3C56234
#define STACK_MAGIC3 0XF31AB123
更进一步地,三个初始魔数数据的偏移量(STACK_MAGIC1_OFFSET、STACK_MAGIC2_
OFFSET、STACK_MAGIC3_OFFSET)定义如下:
#define STACK_MAGIC1_OFFSET 4*SIZEOF(INT4)
#define STACK_MAGIC2_OFFSET 15*SIZEOF(INT4)
#define STACK_MAGIC3_OFFSET 55*SIZEOF(INT4)
即第一初始魔数数据的具体数据为“0XEACD1532”,第二初始魔数数据的具体数据
为“0XD3C56234”,第三初始魔数数据为“0XF31AB123”,上述初始魔数数据均用16进制表示,
每个初始魔数数据占用4个字节,即32位。其中,第一初始魔数数据偏移16个字节,第二初始
魔数数据偏移60个字节,第三初始魔数数据偏移220个字节。第三初始魔数数据距离线程栈
终止地址最远,其魔数偏移量为220个字节,其魔数占用空间为4个字节,从而确定栈保护区
的大小为220+4=224个字节。
在一个实施例中,参见图4,步骤S400包括:
S410,根据线程栈的当前内存空间将线程栈的内存空间扩展为当前内存空间的预
设倍数,扩展后的内存空间作为线程栈的新内存空间。
上述步骤为线程栈内存空间扩展的一种具体实施方式,这种实施方式较易于实
施,只需根据线程栈的当前内存空间的大小在内存中申请一段连续的新内存空间,这个新
内存空间为线程栈的当前内存空间的预设倍数,然后将当前内存空间拷贝到新内存空间
中,从而实现线程栈内存空间的扩展。优选地,线程栈的新内存空间为当前内存空间的两
倍,这样既能实现避免线程栈的溢出,又能避免申请过多的内存空间造成资源的浪费。在另
外一个实施例中,在扩展线程栈的内存空间时,也可根据该线程栈的初始内存空间进行扩
展,例如:当第一次确定栈顶地址位于栈保护区内时,将线程栈的内存空间扩展为初始内存
空间的两倍,当第二次确定栈顶地址位于重设的栈保护区内时,将线程栈的内存空间扩展
为初始内存空间的三倍,以此类推,以满足线程对线程栈的需求,避免线程栈的溢出。
在一个实施例中,当初始魔数数据为多个时,步骤S400还包括:
S420,从多个初始魔数数据对应的魔数偏移量中获得最大魔数偏移量,并根据最
大魔数偏移量和所述魔数占用空间确定栈保护区的内存空间大小。
上述步骤S420为初始魔数数据为多个情况,根据多个初始魔数数据中偏移量最大
的初始魔数数据的魔数偏移量及其魔数占用空间确定栈保护区的内存空间大小。通常情况
下,每个初始魔数数据的魔数占用空间都相同,所以无需特意的去获取偏移量最大的初始
魔数数据的魔数占用空间。在初始魔数数据仅为一个的情况下,只需获得该初始魔数数据
的魔数偏移量及魔数占用空间便可得到栈保护区的内存空间大小。
S430,根据栈保护区的内存空间大小在线程栈的新内存空间中重设栈保护区的起
始地址和终止地址,并将重设的栈保护区的起始地址作为新的栈保护区起始地址,将重设
的栈保护区的终止地址作为新的线程栈终止地址。
在得到线程栈的新内存空间后,便可知该线程栈的新的线程栈起始地址和新的线
程栈终止地址,并在确定栈保护区的内存空间大小后,从新的线程栈终止地址开始向线程
栈内偏移栈保护区的内存空间大小后的位置处作为重设的栈保护区的起始地址,即新的栈
保护区起始地址(栈限制线),而新的线程栈终止地址即为重设后的栈保护区的终止地址。
S440,判断函数数据在线程栈中的栈顶地址是否位于重设的栈保护区内,并在栈
顶地址位于重设的栈保护区内时返回步骤S410,直至将函数数据全部写入线程栈后函数数
据的栈顶地址位于重设的栈保护区之外。
在扩展线程栈的内存空间得到线程栈的新内存空间和得到重设的栈保护区后,函
数数据会继续在线程栈的新内存空间中写入,此时继续判断函数数据在线程栈中的栈顶地
址是否位于重设的栈保护区内,如果栈顶地址再次落入栈保护区内,则再次扩展线程栈的
栈保护区,即返回步骤S410,直至函数数据在线程栈内全部写完,且仍位于线程栈的栈安全
区内,从而有效地防止了函数数据在线程栈中的溢出。
在一个实施例中,在步骤S430之后,还包括:
S430a,将新的栈保护区起始地址和新的线程栈终止地址保存在相应的存储单元
中。
将新的栈保护区起始地址和新的线程栈终止地址保存在相应的存储单元中,便于
判断栈顶地址是否位于栈保护区及再次扩展线程栈时方便新的栈保护区的设置。在一个实
施例中,将新的栈保护区起始地址和新的线程栈终止地址取代保存在存储单元中的原有的
相应的地址信息,以避免资源的浪费。优选地,存储单元为中央处理单元的寄存器。
S430b,根据初始魔数数据的魔数偏移量和魔数占用空间在重设后的栈保护区内
设置新的魔数数据。
在线程栈的新内存空间中重新设置好栈保护区后,为了达到多重保障防止线程栈
溢出的效果,需要在重设的栈保护区内设置多个魔数数据,优选地,在重设的栈保护区内设
置的多个魔数数据与初始魔数数据的魔数偏移量和魔数占用空间相同,从而实现与线程栈
的初始内存空间相同的多重保障效果,并且这样也使得新的魔数数据的设置变得简单。当
然,在重设的栈保护区内设置新的魔数数据时,也可以设置与初始魔数数据的魔数偏移量
和魔数占用空间不相同的新的魔数数据。通常初始魔数数据的魔数偏移量是一种最优的实
施方式,例如:第一初始魔数数据偏移线程栈终止地址较近、第二初始魔数数据偏移线程栈
终止地址稍远些、第三初始魔数数据偏移线程栈终止地址最远,在距离线程栈终止地址较
近的位置处设置较多的魔数数据,因此设置新的魔数数据与初始魔数数据相同的魔数偏移
量和魔数占用空间,可以很好地保障线程栈不会溢出。
需要说明的是,上述步骤S430a和步骤S430b只是为了便于说明,两个步骤之间并
不存在先后顺序。
在一个实施例中,参见图5,在步骤S400之后,线程栈的处理方法还包括:
S500,判断调用函数是否结束,并在调用函数结束后,删除写入到线程栈中的函数
数据。
S600,释放线程栈扩展的内存空间,保留线程栈的初始内存空间。
S700,将线程栈的初始内存空间对应的栈保护区起始地址和线程栈终止地址重新
写入相应的存储单元中。
调用函数结束后,首先,删除写入到线程栈中的函数数据,减少对线程栈内存空间
的占用。然后,释放线程栈中扩展的内存空间,只保留线程栈中的初始内存空间,从而使线
程栈在整个过程中好像没有改变过一样,这样能够减少线程栈在计算机的物理内存空间中
占用,从而实现在极端情况下满足线程栈需求的同时,降低对计算机物理内存空间的占用,
提高计算机中央处理器的处理效率。步骤S700是根据具体的情况而定,如果重设的栈保护
区(新的栈保护区)的起始地址和新的线程栈终止地址不是取代保存在存储单元中的原有
的相应的地址信息,而只是保存在存储单元中,则只需将新的栈保护区起始地址和新的线
程栈终止地址从存储单元中删除即可,如果是取代的方式,则将线程栈的初始内存空间对
应的栈保护区起始地址和线程栈终止地址重新写入相应的存储单元中。在整个实施过程
中,可默认为线程栈起始地址不变。
本领域普通技术人员可以理解实现上述实施例方法中的全部或部分流程,是可以
通过计算机程序来指令相关的硬件来完成,所述的程序可存储于一计算机可读取存储介质
中,该程序在执行时,可包括如上述各方法的实施例的流程。其中,所述的存储介质可为磁
碟、光盘、只读存储记忆体(Read-Only Memory,ROM)或随机存储记忆体(Random Access
Memory,RAM)等。
在一个实施例中,如图6所示,还提供了一种线程栈的处理系统,该系统包括:函数
数据获取模块100,用于根据线程调用的调用函数获得所述调用函数对应的函数数据。栈顶
地址获取模块200,用于将函数数据写入线程栈,并获取函数数据在写入线程栈时在线程栈
中的栈顶地址。第一判断模块300,用于判断栈顶地址是否位于所述线程栈的栈保护区之
内。扩展重设模块400,用于如果栈顶地址位于栈保护区内,则扩展线程栈的内存空间,并在
扩展后的线程栈的内存空间中根据栈保护区的内存空间大小重新设置线程栈的栈保护区,
使栈顶地址位于重设的栈保护区之外。
本实施例中的线程栈的处理系统,通过获取调用函数对应的函数数据在线程栈中
的栈顶地址来实时有效地监控函数数据对线程栈的使用情况,通过在线程栈中设置栈保护
区,并在函数数据在线程栈中的栈顶地址位于栈保护区内时,判定线程栈的当前内存空间
即将使用完,从而及时地扩展线程栈的内存空间,以使栈顶地址始终位于栈安全区之内,避
免函数数据溢出线程栈的现象。
其中,栈保护区为由所述栈保护区起始地址和所述线程栈终止地址界定的内存空
间,栈保护区起始地址位于线程栈起始地址和线程栈终止地址之间。
在一个实施例中,第一判断模块300包括:提取单元310,用于获取设置在栈保护区
内的初始魔数数据,并由初始魔数数据中提取所述初始魔数数据的魔数偏移量和魔数占用
空间;第一确定单元320,用于根据线程栈终止地址和魔数偏移量确定初始魔数数据的魔数
起始地址,并根据魔数起始地址和所述魔数占用空间确定所述初始魔数数据的魔数终止地
址,其中,魔数起始地址与所述魔数终止地址界定的区间为初始魔数数据的魔数占用区;获
取单元330,用于当所述函数数据写入到线程栈后,获取所述魔数占用区中的当前数据;以
及比较单元340,用于将当前数据与初始魔数数据进行比较,并在当前数据与初始魔数数据
不一致时,确定栈顶地址位于所述栈保护区内。
在一个实施例中,扩展重设模块400包括:扩展单元410,用于根据线程栈的当前内
存空间将线程栈的内存空间扩展为当前内存空间的预设倍数,扩展后的内存空间作为线程
栈的新内存空间。
在一个实施例中,当初始魔数数据为多个,每个初始魔数数据对应有不同的魔数
偏移量时,扩展重设模块400还包括:第二确定单元420,用于从多个初始魔数数据对应的魔
数偏移量中获得最大魔数偏移量,并根据最大魔数偏移量和魔数占用空间确定栈保护区的
内存空间大小;重设单元430,用于根据所述栈保护区的内存空间大小在线程栈的新内存空
间中重设栈保护区的起始地址和终止地址,并将重设的栈保护区的起始地址作为新的栈保
护区起始地址,将重设的栈保护区的终止地址作为新的线程栈终止地址;以及判断单元
440,用于判断函数数据在所述线程栈中的所述栈顶地址是否位于所述重设的栈保护区内,
并在所述栈顶地址位于重设的栈保护区内时返回所述扩展单元410,直至将函数数据全部
写入线程栈后函数数据的栈顶地址位于重设的栈保护区之外。
在一个实施例中,扩展重设模块400还包括:保存单元430a,用于在根据栈保护区
的内存空间大小在线程栈的新内存空间中重设栈保护区的起始地址和终止地址之后,将新
的栈保护区起始地址和新的线程栈终止地址保存在相应的存储单元中;以及设置单元
430b,用于根据初始魔数数据的魔数偏移量和魔数占用空间在重设的栈保护区内设置新的
魔数数据。
在一个实施例中,系统还包括:第二判断模块500,用于在扩展所述线程栈的初始
内存空间,并根据所述栈保护区的内存空间大小重新设置所述线程栈的栈保护区,使栈顶
地址位于重设的栈保护区之外后,判断所述调用函数是否结束,并在所述调用函数结束后,
删除写入到所述线程栈中的所述函数数据;释放保留模块600,用于释放线程栈扩展的内存
空间,保留线程栈的初始内存空间;以及重写模块700,用于将线程栈的初始内存空间对应
的所述栈保护区起始地址和线程栈终止地址重新写入相应的存储单元中。
由于此系统解决问题的原理与前述一种线程栈的处理方法相似,因此该系统的实
施可以参见前述方法的实施,重复之处不再赘述。
以上所述实施例的各技术特征可以进行任意的组合,为使描述简洁,未对上述实
施例中的各个技术特征所有可能的组合都进行描述,然而,只要这些技术特征的组合不存
在矛盾,都应当认为是本说明书记载的范围。
以上所述实施例仅表达了本发明的几种实施方式,其描述较为具体和详细,但并
不能因此而理解为对发明专利范围的限制。应当指出的是,对于本领域的普通技术人员来
说,在不脱离本发明构思的前提下,还可以做出若干变形和改进,这些都属于本发明的保护
范围。因此,本发明专利的保护范围应以所附权利要求为准。