请教几个概念性的东西

发表于:2007-05-25来源:作者:点击数: 标签:请教东西几个性的概念
一个进程有代码段,数据段,堆栈段,代码段放的是程序代码应该没错了。 数据段是放一些全局、静态变量吗?malloc,new所申请的内存是不是也放在这儿的?除此之外,还有什么数据会放在数据段? 堆栈段保存的有哪些数据?调用函数时的压栈数据?函数的返回值是

一个进程有代码段,数据段,堆栈段,代码段放的是程序代码应该没错了。
数据段是放一些全局、静态变量吗?malloc,new所申请的内存是不是也放在这儿的?除此之外,还有什么数据会放在数据段?
堆栈段保存的有哪些数据?调用函数时的压栈数据?函数的返回值是放在这里的?局部变量呢?

还有一个, bbs段指的是什么?(不是说的灌水的那个BBS)

 win_hate 回复于:2003-12-05 17:56:45
不是bbs, 是 bss

 gadfly 回复于:2003-12-05 18:07:36
局部变量和返回值都保存在栈中

malloc和new数据保存在堆中

全局,静态和常量保存在bss中

 lenovo 回复于:2003-12-05 18:45:33
我认为返回值不是保存在栈上。
是在别的地方(哪里我也不清楚 :D )
因为返回时栈的数据可能就被销毁了,
返回值也没了。

 win_hate 回复于:2003-12-05 18:52:21
返回值放在寄存器 eax 中,返回地址才放在栈中。

返回值即使放在栈中也未必不行。因为每个进程拥有自己的栈空间,只要在其它函数运行之前,把返回值取出来就行。栈中的数据一般不会被自动销毁,栈指针动了一下而已,数据还在那里。

 stevenphon 回复于:2003-12-05 23:03:58
我看了楼主那些文章,一头雾水,什么寄存器啊,什么栈啊,都不认识`````

如果不懂这些会不会影响学习C语言啊??

望各位大虾给小弟指点迷津~~~~~~~~~ :idea:

 月下雨露 回复于:2003-12-06 00:02:35
呵。。。也许不会有太大的影响 吧。。。。
但是你要设计程序就得了解这些东西哟。。。。祝你好运!!!!!!!!
还是多看看书吧。。。。。

 lcd 回复于:2003-12-06 12:28:48
soory, 还是有几个问题没弄明白
bss具体指的是什么?
堆是指哪一块存储区?
返回值放在寄存器中我想不太可能吧. 如果函数返回的类型是一个复杂的结构或是一个类, 哪个寄存器放的下?!
如果是我的概念比较混乱,请指教. 因为我对这个确实有些糊涂

 win_hate 回复于:2003-12-07 07:42:02
[quote:8c9f2946d7="lcd"]soory, 还是有几个问题没弄明白
bss具体指的是什么?
堆是指哪一块存储区?
[/quote:8c9f2946d7]

.bss 意为 bolck starded by symbol, 用于保存未初始化的符号. bss 是可执行文件中的一段. 所谓的未初始化是说, 此段仅包含了变量的符号和相关信息, 由于变量具体的值还不知道, 所以未给这些变量分配空间. 在程序被加载时, bss段被扩充(为变量分配空间)并映射到内存中的"未初始化数据区", 而实际上相应的值被统一初始化为 0.

堆和栈都是在程序加载时由系统分配的, 进程在内存中的分布大致如下:

高地址 [环境信息] [栈----->] [<-------堆] [未初始化数据] [初始化数据] [正文段]低地址.

APUE 中有一节讲进程环境, 把这些东西说了个大概, 有兴趣的可以参考一下.

 win_hate 回复于:2003-12-07 07:49:00
[quote:80d981ec23="lcd"]soory, 还是有几个问题没弄明白
返回值放在寄存器中我想不太可能吧. 如果函数返回的类型是一个复杂的结构或是一个类, 哪个寄存器放的下?!
如果是我的概念比较混乱,请指?..........[/quote:80d981ec23]

你说得对, 我大意了. :oops:

返回值如何实现取于编译器和采用的编译规则, 其中并没有通用的标准. 比如要从寄存器返回, 但不同体系的机器,其寄存器是不同的, 无法统一. Stroustrup 说有些系统中c++是解析的, 那么这些c++的解析实现采用的返回方式与编译实现采用的返回方式可能也不同. 所以我们只能讨论范围限制在某种特定机器上的某个编译器上.在这里,我们约定是x86/gclearcase/" target="_blank" >cc3 (linux)

当返回值能容纳在一个寄存器中时, 通常都用一个寄存器返回.这是没有问题的. 当返回值足够小能容纳在两个寄存器中, 比如 edx:eax时, 通过这两个寄存器返回. 当要求返回的对象比较大时, 比如 x = foo (), 而 sizeof (x) 比较大, 则调用者将 x 的地址通过栈传递给被调用函数 foo, foo 把返回值写到 x 中. 有点象这样:
将 x = foo (); 
转化为 (void) foobar (&x);

视情况的不同, 调用者在调用前, 也许要为被调用者在堆栈中提供一些空间,供被调用者使用.

再强调一次, 如何返回并不是c的一个组成部分.  c标准是抽象的, 并不关心"实际如何返回". 实际如何返回, 是编译器的事.

 lcd 回复于:2003-12-08 09:20:17
谢谢win_hate。
“堆栈”是“堆”和“栈”的合称吗?请问它们之间是怎么区分的?

 win_hate 回复于:2003-12-08 10:59:13
是否合称我不清楚, 很多时候我说堆栈, 但实际上指的是栈(stack).堆的英文为heap.

栈主要用来存放局部变量, 传递参数, 存放函数的返回地址.esp 始终指向栈顶, 栈中的数据越多, esp的值越小.

堆用于存放动态分配的对象, 当你使用 malloc , new 等进行分配时,所得到的空间就在堆中. 动态分配得到的内存附带有分配信息, 所以你能够 realloc 和 free调它们.

 lcd 回复于:2003-12-08 13:39:07
多谢,  解释的非常清楚, 受益非浅

 蓝色键盘 回复于:2003-12-08 13:57:10
我觉得下面的文章对这个问题描述的比较清晰,参考一下
[code:1:ef5a92a6d9]
进程在内存中的影像. 
      我们假设现在有一个程序, 它的函数调用顺序如下. 
      main(...) -> func_1(...) -> func_2(...) -> func_3(...) 
      即: 主函数main调用函数func_1; 函数func_1调用函数func_2; 函数func_2调用函数func_3 

      当程序被操作系统调入内存运行, 其相对应的进程在内存中的影像如下图所示. 

        (内存高址) 
        +--------------------------------------+ 
        |             ......                   |  ... 省略了一些我们不需要关心的区 
        +--------------------------------------+ 
        |  env strings (环境变量字串)          | \ 
        +--------------------------------------+  \ 
        |  argv strings (命令行字串)           |   \ 
        +--------------------------------------+    \ 
        |  env pointers (环境变量指针)         |    SHELL的环境变量和命令行参数保存区 
        +--------------------------------------+    / 
        |  argv pointers (命令行参数指针)      |   / 
        +--------------------------------------+  / 
        |  argc (命令行参数个数)               | / 
        +--------------------------------------+ 
        |            main 函数的栈帧           | \ 
        +--------------------------------------+  \ 
        |            func_1 函数的栈帧         |   \ 
        +--------------------------------------+    \ 
        |            func_2 函数的栈帧         |     \ 
        +--------------------------------------+      \ 
        |            func_3 函数的栈帧         |      Stack (栈) 
        +......................................+      / 
        |                                      |     / 
                      ......                        / 
        |                                      |   / 
        +......................................+  / 
        |            Heap (堆)                 | / 
        +--------------------------------------+ 
        |        Uninitialised (BSS) data      |  非初始化数据(BSS)区 
        +--------------------------------------+ 
        |        Initialised data              |  初始化数据区 
        +--------------------------------------+ 
        |        Text                          |  文本区 
        +--------------------------------------+ 
        (内存低址) 

        这里需要说明的是: 
        i)   随着函数调用层数的增加, 函数栈帧是一块块地向内存低地址方向延伸的. 
             随着进程中函数调用层数的减少, 即各函数调用的返回, 栈帧会一块块地 
             被遗弃而向内存的高址方向回缩. 
             各函数的栈帧大小随着函数的性质的不同而不等, 由函数的局部变量的数目决定. 
        ii)  进程对内存的动态申请是发生在Heap(堆)里的. 也就是说, 随着系统动态分 
             配给进程的内存数量的增加, Heap(堆)有可能向高址或低址延伸, 依赖于不 
             同CPU的实现. 但一般来说是向内存的高地址方向增长的. 
        iii) 在BSS数据或者Stack(栈)的增长耗尽了系统分配给进程的自由内存的情况下, 
             进程将会被阻塞, 重新被操作系统用更大的内存模块来调度运行. 
             (虽然和exploit没有关系, 但是知道一下还是有好处的) 
        iv)  函数的栈帧里包含了函数的参数(至于被调用函数的参数是放在调用函数的栈 
             帧还是被调用函数栈帧, 则依赖于不同系统的实现), 
             它的局部变量以及恢复调用该函数的函数的栈帧(也就是前一个栈帧)所需要的 
             数据, 其中包含了调用函数的下一条执行指令的地址. 
        v)   非初始化数据(BSS)区用于存放程序的静态变量, 这部分内存都是被初始化为零的. 
             初始化数据区用于存放可执行文件里的初始化数据. 
             这两个区统称为数据区. 
        vi)  Text(文本区)是个只读区, 任何尝试对该区的写操作会导致段违法出错. 文本区 
             是被多个运行该可执行文件的进程所共享的. 文本区存放了程序的代码. 

    2) 函数的栈帧. 
       函数调用时所建立的栈帧包含了下面的信息: 
       i)   函数的返回地址. 返回地址是存放在调用函数的栈帧还是被调用函数的栈帧里, 
            取决于不同系统的实现. 
       ii)  调用函数的栈帧信息, 即栈顶和栈底. 
       iii) 为函数的局部变量分配的空间 
       iv)  为被调用函数的参数分配的空间--取决于不同系统的实现. 
[/code:1:ef5a92a6d9]

 蓝色键盘 回复于:2003-12-08 14:00:09
还有一篇文章,从另外一个侧面可以了解进程环境

http://www-900.ibm.com/developerWorks/cn/linux/kernel/l-page/index.shtml

 gadfly 回复于:2003-12-09 18:20:46
对,上面我的解释有点不准确。

全局,静态和常量是分配在数据区中的。数据区包括bss和初始化区。

原文转自:http://www.ltesting.net

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)