精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-01-17
Arath 写道 Elminster 写道 七猫 写道 从理论上来都是在第一次使用前构造好,C++的全局变量的构造次序似乎难以保证。
全局变量理论上只能保证在 main 函数之前构造完毕,同时一个翻译单元内的全局变量按声明次序构造,除此之外没有任何保证,所以万一一个全局变量构造时试图访问另一个全局变量的话,很容易出问题。而局部静态变量则保证在第一次调用时构造,这个确定性强多了。 不知道为什么会提出全局变量构造难以保证,这一点必须是编译器与操作系统协调好的,否则后果不堪设想. 另一个问题,如果全局遇到的那个问题那么局部也逃不掉,所以如果从这方面说两者没有什么区别,区别还在于作用域上,当然采用何种方法还在于人的习惯. 无论是全局的还是局部的,其构造都是由编译器产生额外的代码,然后将这个代码放在正确的入口处,这一点任何C/C++编译器都不会有什么大区别. Elminster的意思应该指的是 全局对象初始化顺序的问题。 这个在不同的编译单元之间是没有任何保证的。 不知道你为啥 能把这个 扯到 操作系统上去? 函数内局部的静态对象,可以在函数第一次被调用时初始化,所以你程序中调用次序就决定了初始化顺序,明白了没? 记的你说自己,搞了个2w行一个的函数,现在我大概能猜出来是啥样了,呵呵.... |
|
返回顶楼 | |
发表时间:2007-01-18
BTW:我觉得老谭不算误人子弟吧,很多人都是从他的那本书开始的,我也是。老谭的书我感觉有种朴素美。
|
|
返回顶楼 | |
发表时间:2007-01-18
runes 写道 Elminster的意思应该指的是 全局对象初始化顺序的问题。 这个在不同的编译单元之间是没有任何保证的。 不知道你为啥 能把这个 扯到 操作系统上去? 函数内局部的静态对象,可以在函数第一次被调用时初始化,所以你程序中调用次序就决定了初始化顺序,明白了没? 记的你说自己,搞了个2w行一个的函数,现在我大概能猜出来是啥样了,呵呵.... 可见你没有搞过编译器,编译器在很多地方都要依赖于操作系统,如果你要用“扯到”一词只能说明你自己不了解罢了. 重复我的观点,如果编译器无法保证全局变量的成功初始化,那么这个编译器没有人敢用,可以去看看纯C的代码,成千上百的全局变量,如果编译器无法保证这些变量被正确初始化,谁还敢用. 说到初始化顺序,这一点我没有说不对,所以我也不提了,这个完全在于开发人员自己的开发规划. 至于你最后说的那句话似乎只能体现你的“小”而已. |
|
返回顶楼 | |
发表时间:2007-01-18
七猫 写道 BTW:我觉得老谭不算误人子弟吧,很多人都是从他的那本书开始的,我也是。老谭的书我感觉有种朴素美。
谭浩强的那本C书的确很基础,对于新学者还有可以的,但是其中很多代码所传递的喜欢不好,如果一旦适应了就对以后做真正的开发有不好的影响. 我也看过老谭的那本书,后来在图书馆自己借到了另一个C的书,感觉真的是天壤之别,于是马上就丢掉了老谭的书. 现在唯一遗憾的是我把那本书的名字和作者忘记了 ![]() 另,老谭的书当年创下了中国发行量第一,主要还是归功于各大专院校以其作为课本吧 ![]() |
|
返回顶楼 | |
发表时间:2007-01-18
Arath 写道 runes 写道 Elminster的意思应该指的是 全局对象初始化顺序的问题。 这个在不同的编译单元之间是没有任何保证的。 不知道你为啥 能把这个 扯到 操作系统上去? 函数内局部的静态对象,可以在函数第一次被调用时初始化,所以你程序中调用次序就决定了初始化顺序,明白了没? 记的你说自己,搞了个2w行一个的函数,现在我大概能猜出来是啥样了,呵呵.... 可见你没有搞过编译器,编译器在很多地方都要依赖于操作系统,如果你要用“扯到”一词只能说明你自己不了解罢了. 重复我的观点,如果编译器无法保证全局变量的成功初始化,那么这个编译器没有人敢用,可以去看看纯C的代码,成千上百的全局变量,如果编译器无法保证这些变量被正确初始化,谁还敢用. 说到初始化顺序,这一点我没有说不对,所以我也不提了,这个完全在于开发人员自己的开发规划. 至于你最后说的那句话似乎只能体现你的“小”而已. 原来是你自己树了个把子打着玩啊! 这里有谁说的没有依赖全局变量初始化问题了,都说的有依赖的,建议你自己仔细再看看帖子。 下面的讨论,就局限于你的靶子 “不依赖于其他全局变量的全局变量初始化问题” 你说 “可见你没有搞过编译器”,嗯,我的确没有搞过,所以不敢装蒜,不过我认为,单一的全局变量初始化应该和 操作系统没有关系。这个应该在编译时就决定了。 听你话里话外的,似乎搞过编译器咯,但愿你不是装蒜,那不妨说说看看,这个全局变量初始化到底哪里依赖于操作系统。 不要告诉我,当程序执行时,需要操作系统的loader先做一把动作,hoho...,这个谁都知道。 至于最后一句吗,仁者见仁,智者见智,当然,淫者也见淫,脑子长在你身上,怎么想,是你的自由..... |
|
返回顶楼 | |
发表时间:2007-01-18
我所提出
引用 不知道为什么会提出全局变量构造难以保证,这一点必须是编译器与操作系统协调好的,否则后果不堪设想
是针对 Elminster 写道 全局变量理论上只能保证在 main 函数之前构造完毕,同时一个翻译单元内的全局变量按声明次序构造,除此之外没有任何保证
而来,你就抓住了操作系统这一点和我掰. 一般来说编译产生的最终代码中,需要初始化的数据都会被放在一个initialized data section中,这样操作系统支持的话就可以直接在进入main之前将这个section中的值来初始化对应的内存区域, 但是在某些操作系统中,loader不具备这个功能甚至没有loader,如果这样就需要编译器产生初始化全局变量的代码放在main之前执行. 正是基于这一点我才会说“编译器与操作系统协调好”. 现在明白了不? 讨论技术有争执没有什么,但是要上升到人身攻击那就只能说明自身的粗浅. 到此为止,我不会再回你任何帖子! |
|
返回顶楼 | |
发表时间:2007-01-18
现在这个问题也越来越深入了,正因为大家的讨论,才能碰撞出火花,把问题给剖析的比较深入.
作为lz, 我很高兴大家的踊跃发言,讨论的时候有技术上的争执,思想上的差异,都是非常正常的.不过这样子,我们才会一起进步,一起克服问题. 希望我们讨论的时候,能做到对事不对人,努力构造一个自由和谐的讨论环境. |
|
返回顶楼 | |
发表时间:2007-01-19
Arath 写道 我所提出
引用 不知道为什么会提出全局变量构造难以保证,这一点必须是编译器与操作系统协调好的,否则后果不堪设想
是针对 Elminster 写道 全局变量理论上只能保证在 main 函数之前构造完毕,同时一个翻译单元内的全局变量按声明次序构造,除此之外没有任何保证
而来,你就抓住了操作系统这一点和我掰. 一般来说编译产生的最终代码中,需要初始化的数据都会被放在一个initialized data section中,这样操作系统支持的话就可以直接在进入main之前将这个section中的值来初始化对应的内存区域, 但是在某些操作系统中,loader不具备这个功能甚至没有loader,如果这样就需要编译器产生初始化全局变量的代码放在main之前执行. 正是基于这一点我才会说“编译器与操作系统协调好”. 现在明白了不? 讨论技术有争执没有什么,但是要上升到人身攻击那就只能说明自身的粗浅. 到此为止,我不会再回你任何帖子! 呵,“同时一个翻译单元内的全局变量按声明次序构造,除此之外没有任何保证”,我认为就是指的有依赖的关系的那种,要不干吗提“声明次序构造”呢? 需要初始化的数据都会被放在一个initialized data section中,和“没有依赖关系的全局变量初始化的值”之间有关系吗? 那个值编译期就决定了。 “样操作系统支持的话就可以直接在进入main之前将这个section中的值来初始化对应的内存区域” 你那“个section中的值”是不是编译期定下来的??? 如果你非得强调 操作系统初始化section,我感觉就像说“每个月的薪水(公司给你定好的)是依赖于ATM机(取款方式)”。 至于你说什么人身攻击吗,随你怎么想,我感觉论坛里面说话吗,直接一些大家简单明了,观点尖锐一些很快就能把问题讨论清楚,还是那句话,智者见智,仁者见仁,当然淫者也见淫。 最后,你说“到此为止,我不会再回你任何帖子!” 呵呵,我又不需要 有人来给我抬轿子,爱回不回,你的手长在你身上,没有人强迫你,请随意! |
|
返回顶楼 | |
发表时间:2007-01-19
你说的可能是linux中的.bss或者是pe中的.data段之类的东东吧?这些当然可以由加载器帮你搞定,其实你可以直接用ultraedit或者ida打开的,这些本来就是已经初始化好的变量在里面,加载器基本上只要把他们直接读到内存就可以了。
但我认为我们讨论的不仅仅是: static int g_systeminit=1;这么简单的事情,我们要讨论的可能还涉及到类的构造函数,这个一般是加载器调用程序的一个入口函数,这个入口函数并不是你平时所写的main,WinMain函数,而是编译器内部的一个(WIN下面的maincrtstartup,在这里面可能会做这些全局变量的初始化的工作),我前面仅仅提到次序问题,而不是他们是否能确保的问题。 次序就是你要是两个全局变量(他们都有构造函数),这两个全局变量的初始化次序可能是无法确定的。 这是我的印像中的理解,但我也记不太清楚C++库里的全局变量的构造函数在何时会被调用,可能是入口后的那部分吧,楼上那位搞过编译器的兄弟能否给我们讲解一下编译器是怎么处理这块内容的呢? |
|
返回顶楼 | |
发表时间:2007-01-19
#include <stdio.h>
#include <stdlib.h> class CA { public: CA() { printf("Enter %s\n",__FUNCTION__); } ~CA() { printf("Leave %s\n",__FUNCTION__); } }; class CB { public: CB() { printf("Enter %s\n",__FUNCTION__); } ~CB() { printf("Leave %s\n",__FUNCTION__); } }; CA gca; CB gcb; int i=1; int main(int argc,char *argv[]) { printf("We are coming...%d\n",i); return 0; } 如上面的这个例子, 其中i是放在数据段,已经被初始化好了,就是1, CA,CB的构造函数是放在好像是一个表里面的,由MainCrtStartup来执行(用_init_term来完成的),有兴趣的可以直接看C库代码。我不贴了。 |
|
返回顶楼 | |