迁移北京已有数月,近距离的看北京,发现很多很有趣的地方。这实在是个神奇的城市,好像什么事情都有可能发生。
平日里每每看到有趣的场景都需要对自己重复一下:
“这是个神奇的城市,不要惊奇、不要惊奇…..”
场景一:
每日上班下班都是件复杂的工程。
首先,出门步行200米之后走到小区门口,需要经过一个相当开阔的马路,这个马路的确相当的开阔,如果把“辅路”这种奇怪的设计也算在内的话,是8车道。这个路口经常有无视红灯冒着呼啸而过的小车经过。幸好上班时间人流量比较大,小车们除了轧轧禁停线倒也不算太出格。顺便打个岔,让我尤其觉得有趣的是,拥有如此开阔的马路的回龙观居住区,号称容纳了百万居住者的人圈,连接通向老城区的道路的交流道居然仅仅是可怜的双车道。据说自驾上班的话,有可能开了半个钟头还堵在交流道上。
然后,回龙观城铁站也是个很有趣的地方。它旁边就是一个从google map上可以看到的黄色主干道(也就是偶上面提到的8车道的路),而这个车站不知道设计的时候出发点是什么,道路很崎岖,至少从我出发的路线来看很崎岖,倒是有一条路很方便,但如果我没有理解错的话,那条路主要是通达老城区的一条窄窄的干道,对于真正居住在这附近以城铁为主要交通工具的居民而言,道路是很崎岖的。
以我每日的行程为例,在穿过那条危险的马路之后,需要爬过一个黑漆漆的桥下斜坡,这里居然没有路灯?! 晚上的时候我经常想带个电筒,不然很容易在这条路上撞上人或者踩到什么莫名物体。
而且同时也很不理解的是,为何在这个斜坡路口长期放着两个塑胶的大半人高的大垃圾桶?! 这是交通路线啊,或者是这两个垃圾桶是打算用作城市里道路旁的那种收集箱的作用?说真的,这还真挑战我的想象力。怎么看都觉得这个垃圾桶是小区设计不合理时临时使用的生活垃圾收集容器。
爬到车站了,想进去?对不起,高峰期限流,这一侧的门封闭了,只出不进,您得绕个道。通过像灌肠机一样的队列,慢慢蠕动到车站里。
来个图吧,不然不容易理解。
绿色的就是我每天早上8点多需要例行的步行路程:

每日路线图
我实在不是很理解这个设计思路。就不拿它和东京比了,和广州香港的风格也迥异的厉害了点。貌似这个地铁并不是为方便人设出行计的,携带一些乘客只不过是这个地铁设计的第二副职,主旨是“轨道交通?我们有啊。城铁啊,很方便的”
大杂烩
有人能告诉我为什么这个主题在IE下显示不是居中的么?
我对css实在陌生的厉害,嗯嗯,确切说对html也不大熟。粗略在网上翻了翻好像css在firefox和IE下的工作经常需要调来调去的。真是个麻烦的东西。
—– 上面这个摆平了,记个笔记:
firefox里,这个主题的主容器container的div,样式设置属性magin:0 auto;就可以,表明到左右两侧的距离自动设置,上下为0。
而IE里自动设置就贴在一边了,其实我个人觉得这也不坏。不过两个浏览器行为不一致还是蛮麻烦的。IE里需要给body设置一个text-align:center,可以居中。但这个属性会继承下去,所以需要在主容器里再显式声明一下text-align:left。
总结:
<body style=”align-text:center;”>
<div id=”container” style=”magin:0 auto;align-text:left;”>
…….
===========
不过这样改又有了新问题,底部的footer在page里好像样式又出岔子了,缩到左侧了。。。。。
另外,还有个小毛病,好像标题下面有个灰色的条,在firefox里不会出现这种跑版的现象。有人帮忙不?
大杂烩
案例4:被改变的入口参数
错误引用:不祥
现象:
某函数Method(int nParamSize, char *pszParamBuf)。调用Method时送入nPathSize, pszFilePath作为入口参数,在函数返回之后。发现nPathSize被变更。
现象分析+排错过程:
现象1:首先代码复查,是否由于笔误错误使用了引用类型。
代码复查无误,则需检查Method函数内部进行了哪些操作。因C/C++规定,函数的入口参数群和函数内部的局部变量事实上是存在于同一块堆栈区域的。
比如,类似
int Function(int nParam1, int Param2, int Param3)
{
int nVar1;
char *pszVar2;
long nVar3;
}
结构如图:
|
栈顶
|
|
|
nVar3
|
|
|
pszVar2
|
|
|
nVar1
|
|
|
函数返回地址
|
|
|
copy_nParam1
|
|
|
copy_nParam2
|
|
|
copy_nParam3
|
|
情况2:可能影响到nPathSize的值的范围,应该在nPathSize定义区域的位置。nPathSize定义位置上下文:
int nSomeData = -1;
int nPathSize = 0;
char szFilePath[256] = { 0 };
分析:正常情况下。声明为类似int这种值传递参数方式时,相应函数调用送入参数是使用拷贝方式将该类型复制在堆栈空间内(这也就是为什么尽量避免使用对象参数的原因),复制过去的值和原来的值是没有关连的,即使在函数内部将这个参数作为局部变量使用,也不应该会影响到外部的值。
可以看到Method有两个参数,第二个参数是一个指针pszFilePath,结合情况2,OK,问题就在这里了。
Method方法传入入口参数时,会将pszFilePath本身的值—也就是指针的值—复制在堆栈内,如果在Method方法内部操作pszFilePath缓冲区,事实上也就是在操作调用Method方法的函数的堆栈空间。如图:

Method方法内部对pszFilePath进行了内存拷贝操作(strcpy/memcpy/…),而超出了pszFilePath分配的内存块大小,导致覆盖了nPathSize的值。如果szFilePath变为pszFilePath改在堆上进行内存动态分配,也有可能影响到邻近的内存块的值。导致出错。
将szFilePath声明的内存块扩大增容,故障消失。
点评:
堆栈/函数入口参数/函数返回地址在内存中存放在连续的空间上,稍有不慎,就有可能导致出错。严重的情况下,如果覆盖掉函数返回地址,则程序将会在函数返回时跳转到到未知地址,此时程序很容易产生莫名的错误乃至崩溃。著名的缓冲区溢出漏洞其实使用的就是这种原理,只不过在溢出的数据中经过精细的构造,可以控制在溢出时覆盖堆栈中的返回地址为攻击者所期望的地址,然后开始执行蠕虫代码。
很简单,不是么。
大杂烩
最近评论