2007年4月26日

"null pointer assignment"的由来

很久以前见到过,当时不明白,看了《C专家编程》后明白了
Thanks to sendoh

"无效的指针可能成为程序员的噩梦,人们很容易用一个无效的指针来引用内存。在所有的虚拟内存结构体系里,一旦一个指针进行解引用操作时所引用的内存地址超出了虚拟内存的地址空间,操作系统就会终止这个进程。但MS-DOS并不支持虚拟内存,即使内存访问失败,它也无法立即捕捉到这种情况。
然而,在MS-DOS系统中可以动点小脑筋,在程序结束后检测解除引用空指针的情况,在Microsoft C和Broland C中都采取了这种方法。在进入程序之前,保存内存地址为零的(内存)的值。在程序结束时,系统检查这个地址的值与原来的是否相同。如果不同,基本上可以确定你的程序中使用了空指针来访问内存,运行时系统会打出一条"null pointer assignment"信息"。

更有趣的事情发生在《创世纪 VI》的一个副产品上,Saveage Empire。是《游戏编程全接触》的作者说的。在快要发布的时候屏幕上会打印"Error:(null)pointer assignment",然而空指针很难被找出,于是这样修复了这个问题,用16进制编辑器修改了可执行文件中的这个文本串改为"Thanks for playing Savage Empire."。注意,它们是等长的...

2007年4月19日

Logger中操纵器的实现

代码下载
我突然想起 std::endl 这样一个东西,很想看看究竟它是怎么实现的.就像jjhou先生在<<stl 源码剖析>>中说的"under the hood".
endl的实现(Visual Studio 7.1版本):
代码下载
我突然想起 std::endl 这样一个东西,很想看看究竟它是怎么实现的.就像jjhou先生在<<stl 源码剖析>>中说的"under the hood".
endl的实现(Visual Studio 7.1版本):

_CRTIMP2 inline basic_ostream<char, char_traits<char> >&
__cdecl endl(basic_ostream<char, char_traits<char> >& _Ostr)
{ // insert newline and flush byte stream
_Ostr.put('\n');
_Ostr.flush();
return (_Ostr);
}
流的这一端:
    _Myt& operator<<(ios_base& (__cdecl *_Pfn)(ios_base&amp;))
{ // call ios_base manipulator
(*_Pfn)(*(ios_base *)this);
return (*this);
}
基本原理就是:
1.模板特化了operator<<的一个版本.
2.使用了访问者模式,最终endl调用的还是_Oster的成员函数.
应用到Logger上:
class Logger
{
public:
typedef Logger& (*pfn)(Logger& );

Logger& operator<<(pfn mani)
{
mani(*this);
return *this;
}
......
};

Logger el(Logger& stream)
{
stream << '\n';
return stream;
}
测试一下:
P.S.把模板代码贴成html真是麻烦<要换成&lt;,>要换成&gt;,连&自己也要换成&amp;有没有简单点的办法...
测试一下:
Logger a;
a << 1 << el << std::string("(temp comment)") << el;
a << 1.001 << el << 't' << el;
a.Print();
system("PAUSE");

Release下调试心得

上周末做的这样一次调试,不过最终并没有找到那个诡异的bug
还是明白了一些事情,首先感谢joehust,让我知道,release下调试时IDE给的变量值并不可靠.
最可靠的办法是写一个Logger.
开始看到调试时变量的值跟我预想的完全不一样让我很奇怪.由于代码优化,很多变量的内容观察不到,行的运行顺序也跟想象的不一样,很多行由于被优化掉无法设置断点.
能相信的就只有这么一个Loggor,把变量的内容输到Logger中记录下来.
简单的Logger实现


class Logger
{
public:
template < T value >
Logger& operator <<(T value)
{
std::stringstream ss;
ss << value;
buffer_.append( ss.str() );
buffer_.push_back('\n');
return *this;
}

void Out(const char *file)
{
std::ofstream fileStream;
fileStream.open(file, std::ios::ios_base::app);
fileStream << buffer_;
fileStream.close();
}

void Print()
{
std::cout << buffer_;
}
private:
std::string buffer_;
};

主要是利用stringstream吧一些常用的类型(int,char,float,double等)转换为字符串

Dian团队五周年庆典

Dian Group's Five Year Anniversary
过了两周了才写,最近一直很忙.
但是发现这样也好,很多事情推迟做更有好处.
李培根校长也来了,让团队的人深受感动.李校长让我感觉是很有感情的那样的人.第二天在集贤楼聚餐
(与我素来景仰的aw合影)
aw谈到的产品化让我感触很深,产品化毕竟和简单的与项目结合不同.
尽管团队人员流动比较频繁,尽管不是以公司的形式运作,产品化是我们的远景.
想起以前钟老师做的"Dian团队的产品化之路",真是很有远见