博文

目前显示的是 十月, 2006的博文

SML简介

SML是指Standard Meta-language
ML(Meta-Language)是一门较早的Functional Language,是当时Type
System理论发展到巅峰时期的作品。由于Type
System和定理的机器证明之间的强烈对应性质,ML从设计之初,就主要被广泛用于定理的机器证明领域,而Lisp,则是较为大众化的Functional
Programming language,活跃在AI的各个领域。
ML后来出现了很多方言,例如Caml。
为了结束混乱局面,于是人们开始着手制定ML的标准,标准化后的ML称为Standard ML(SML)
SML的第一个标准是在84-88年制定,90年颁布,《 Definition of Standard ML》, (Milner,
Tofte, Harper, MIT Press, 1990)。称为SML-90
第二个标准是SML 97。 《The Definition of Standard ML (Revised) 》(Milner,
Tofte, Harper, MacQueen, MIT Press, 1997)
SML 97的一个重要特点就是语言规范中加入了SML 基本标准库。
SML 97的三个主要亮点:
1。The elimination of imperative type variables. The role of imperative
type variables in constraining polymorphism in the presence of effects
is now played by the value restriction, which allows the type of a val
binding to be generalized only when the right hand side is an
expression in a restricted form called a value expression. A value
expression is either a constant, a variable, a function expression
(i.e. a lambda expression) or is built from these elements usin…

把gnome的默认的window manager换成sawfish

只需要三句命令
# portinstall sawfish
# killall metacity; sawfish &
# gnome-session-save --gui

xrandr,查看X的分辨率

用xrandr命令可以查看X的分辨率和刷新率
例如:
$ xrandr
SZ: Pixels Physical Refresh
*0 1024 x 768 ( 321mm x 241mm ) *85
1 800 x 600 ( 321mm x 241mm ) 85
Current rotation - normal
Current reflection - none
Rotations possible - normal
Reflections possible - none

让gnome别用utf-8

我的向来用惯了gb2312,GBK,但是gnome默认用的就是utf-8.而我的文件大多数都是以 GB2312的方式存储的,文件名也是,挂载windows下分区的时候用的也是GBK,于是乱码是免不了的。
我找啊找,原因在哪里呢?
后来发现是gdm的错。
解决方法是:打开/usr/local/etc/gdm/locale.alias
找到zh_CN.UTF-8,然后把zh_CN.GBK加在它前面即可。

gnome-terminal 2.16用起来不习惯

1。没有了工具栏
2。以前的快捷键都不能用了。我现在想复制一段文字都十分困难。
3。我习惯了用Ctrl+Shift+n开一个新terminal,现在也不行了。
4。它似乎改用了从*.glade文件动态载入 GUI,更慢了。

less的字符集设置与汉字编码范围

我们发现,有时候,用less打开一个文件显示的是乱码,而有时候,是正常的。
有两个关键性的环境变量与此有关
LESSCHARSET 和 LESSCHARDEF 。
先解释一下less是怎么解析字符的。
less把字符分为3类。
普通字符(normal characters):可以直接在屏幕上显示
控制字符(control characters):文本文件中的控制字符,不能直接在屏幕上显示,例如回车,换行
二进制字符 (binary characters):除以上之外其它的字符。
为了说明一个字节究竟是属于这三者的哪一类。我们需要用LESSCHARDEF 环境变量来说明。
例如
setenv LESSCHARDEF 8bcccbcc18b95.b
其中,"b"代表binary,"c"代表control,"."代表normal
8bcccbcc18b95.b的含义是:
0x0-0x7是binary characters
0x8 是control character
0x9 是control character
0xA 是control character
0xB 是binary character
0xC 是control character
0xD 是control character
然后下面18个是binary characters,0xE-0x1F
0x20-0x7F,一共95个字符是normal characters
后面的,其他的未知的,统统是binary characters.
我目前用的less的版本是less 381,Copyright (C) 2002 Mark Nudelman。
下面看一张表,是LESSCHARSET和LESSCHARDEF 。
ascii 8bcccbcc18b95.b
dos 8bcccbcc12bc5b95.b.
ebcdic 5bc6bcc7bcc41b.9b7.9b5.b..8b6.10b6.b9.7b
9.8b8.17b3.3b9.7b9.8b8.6b10.b.b.b.
IBM-1047 4cbcbc3b9cbccbccbb4c6bcc5b3cbb…

编译mplayer.Pre8的时候出错

demux_ogg.c:363 error: invalid
operands to binary &

又上不去QQ了

QQ: Using UDP without proxy
QQ: Connected.
QQ: ==> [09517] QQ_CMD_GET_LOGIN_TOKEN, from (QQ Server 0000)
QQ: ack [09517] QQ_CMD_GET_LOGIN_TOKEN, remove from sendqueue
QQ: ==> [09518] QQ_CMD_LOGIN, from (QQ unknown version)
QQ: ack [09518] QQ_CMD_LOGIN, remove from sendqueue
QQ: Decrypt login reply packet with inikey, 110 bytes data[0] is 6
QQ: Unknown reply code: 6

病毒带来的记忆

昨天,用xlock锁屏幕的时候突然看见一句很熟悉的文字。
“All work and no play make Jack a dull boy”
我诧异的看了好一半天,好熟悉的文字啊。
是什么呢?
我在unix的history中拼命搜索。
找不到什么。
后来意外的,在一篇介绍病毒的文章中发现。
这是,一个早期的,很出名的病毒!
“Today is Sunday ! Why do you work so hard ?
 All work and no play make you a dull boy !
Comeuon ! Let’ s go out and have some fun !”
当然,这句话本是是一句俗谚,出处不祥。有英语专业的路过,麻烦帮我查下。
Thanks!

指针的安全性

指针和引用几乎是每个语言的必要元素。即使是ocaml这样的函数式语言,也不得不提供这样的东西。
先考虑,一个语言中为什么要有引用。
假如该语言中的所有函数的参数都是按值传递,而且变量只有值类型,没有指针和引用。那么我们根本无法实现最、最基本的,swap这样的函数。
而对于函数式语言,引用,有2个作用
1。为变量添加别名
2。提供一种修改变量值的方式。
例如
# let x=10;;
val x : int = 10
# let y= ref x;;
val y : int ref = {contents = 10}
# y := 5;;
- : unit = ()
# !y;
;;
- : int = 5
# x;;
- : int = 10
y的值通过赋值运算符号被改变,而x的值不受影响。
下面演示 mutable的单元
# let r=ref 13;;
val r : int ref = {contents = 13}
# let s=r;;
val s : int ref = {contents = 13}
# s :=82;;
- : unit = ()
# !r;;
- : int = 82
可以看到,r的值,悄悄的通过s改变了。
我们简单的将其来看作一个指针,那么对于一个指针,它有最简单的2种运算,引用与解引用
比较 引用 解引用
C p=&x; *p;
ml p=ref x; !p;
先看引用。
首先,当一个指针被创建的时候。
1。根据所指向的类型,可以推导出该指针的类型。
2。它的类型就此确定,且不应该再改变。
如果我们不是在它被赋值的时候就把它的类型记录下来,而是到了后面根据它所出现的位置而动态推导它的类型。那么将会出现非常尴尬的,循环依赖的状况。例
如:
(l →
λx:Nat.(!m)x,
m → λx:Nat.(!l)x).
再看解引用。
首先,如果要对一个指针解引用,那么,我们必须要能确定该指针指向的是什么类型。否则我们就无法知道解引用返回的是什么类型。那么就无法对它所在的表达式
进行类型推导,这是违反基本的类型安全规则的。
大多数情况下,我们很容易得知一个指针的类型。
但是,如果我们对该指针进行了某种运算的话。
例如
char* p=&x;
p++;
现在p指向的是什么类型呢?
如果我们再写
*p;
那么它的执行状况将是未知的。
(回想STL,它将iterator明确的分为5种类型。其中最基础的三种是input iterato…

麻烦

升级linux_base到fc4后,运行dgen出现
"init SDL: No available video device"
而gens则是彻底一闪而过,什么都没有

为什么要引入类型?

如果每个变量都没有类型,那又如何? 类型信息,可被用来判断一个表达式是否是可求值的。 即,在不知道这个表达式的各变量的值的情况下,
之根据上下文类型信息,
静态判断该表达式是否是可求值的,且推导出该表达式的的结果类型。 什么样的表达式是合法,但是不适合作静态类型推导的?
例如这样的
x?3:true
我们无法得知该表达式究竟是会返回一个整数类型的值还是一个bool类型的值。
于是无论是C还是ocaml,都规定其两个分支必须返回相同类型的值。 再例如: struct Pair{ int first; int last }; int x; Pair p; ... if(x?3:p){ } 如果这样的代码也合法,那么我们无法静态的检查if条件语句的语法有效性。
再设想一下,C是完全没有动态类型信息的。C++本来也没有。
如果我们是在运行时才发现我们将错误的类型传递给了if的条件子句。那么……
1。程序只能异常的执行,或者突然终止而且我们不知道它为什么会终止
2。我们无法给出任何有价值的出错信息。只能告诉用户if语句执行失败。 于是我们为项引入类型信息。
但是,我们希望:
去处类型信息后再求值,与求值后再去除类型信息,应该得到相同的结果。 就好比一致连续性对于函数算子的可交换性一样,上面的限制,对于有类型项的求值运算,至关重要。 我希望能在图书馆找到martin-lof类型理论方面的书籍,尽管这已经是40年前的理论了。 再说序列点。
C/C++中的分号被称作一种senqence point,它标志着一个语句的结束。
那么,其语义是什么? 如果把每一行语句都抽象成一个函数。那么可以把其变量值的上下文理解为函数参数,把其返回值,作为下一个函数的参数。
只不过,下一个函数的执行过程中永远用不到这个参数。 从lambda演算的角度来讲。
m;t
可以被理解为
λx.t m
其中项t中不含有x.

nv的显卡驱动爆出严重的安全漏洞

http://www.vuxml.org/freebsd/a6d9da4a-5d5e-11db-8faf-000c6ec775d9.htmlThe NVIDIA Binary Graphics Driver for Linux is
vulnerable to a buffer overflow that allows an attacker to run
arbitrary code as root. This bug can be exploited both locally or
remotely (via a remote X client or an X client which visits a malicious
web page). A working proof-of-concept root exploit is included with
this advisory. The NVIDIA drivers for Solaris and FreeBSD are
also likely to be vulnerable. 4。 Solution Disable the binary blob driver and use the
open-source "nv" driver that is included by default with X. 如果你不希望你的电脑直接这么轻松被hacker操控的话,那么唯一的解决办法就是暂时不要使用nv的开
发的该显卡驱动。使用你的X server自带的驱动

使用 GNU CC 的预编译头文件加快编译速度

intron写的,很不错!

重回FreeBSD

经过几天几夜的奋斗,学校的上网客户端再次被破解。
于是,我又可以舒服的在FreeBSD下上网了。
于是,我暂时又不必担心硬盘不够用了。FreeBSD下一共80G的硬盘,现在还剩30G呢。
哎,开心!
说下这次的心得。
破解的时候,一定要静态代码分析与动态调试双管齐下,说简单点,就是IDA和ollydbg切换着来。
对于ASProtect的壳,恢复IAT后,即可用ollydbg调试了。不用再补区段再做一下步了。
另外,ethereal和ollydbg不能同时开,否则,系统一定僵死!

IAT表

IAT的全称是Import Address Table。
对于每一个引入的可执行文件(例如dll),有一个镜像引入描述符(IMAGE_IMPORT_DESCRIPTOR)。typedefstruct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics; // 0 for terminating null import descriptor DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) }; DWORD TimeDateStamp; // 0 if not bound, // -1 if bound, and real date\time stamp // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) // O.W. date/time stamp of DLL bound to (Old BIND) DWORD ForwarderChain; // -1 if no forwarders DWORD Name; //RVA,指向字符串,是这个可执行文件的名字。例如"ACE.dll" DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) } IMAGE_IMPORT_DESCRIPTOR; dll的forward不好讲,因为很多都是undocumented的.我们着重关心两个指针,OriginalFirstThunk和FirstThunk。
Characteristics一词出于历史原因,故在此给它了一个别名,OriginalFirstThunk。
OriginalFirstThunk和FirstThunk是两个DWORD值,存贮着两个RVA数值,其实它们就是两个指针。
OriginalFirstThunk和FirstThunk实际上都是指向同一个数组。
前者,我们称之为INT,而后者,我们称之为IAT.IAT是一个IMAGE_THUNK_DATA类…

memcpy的效率

有些刚开始学C++的人误以为,有了std::copy就不需要memcpy这样的低级C函数了。
而事实上,memcpy的最大的好处,还是在于它的高效。我也是最近两天反编译C程序的时候才发现这一点。
众所周知,memcpy这样的函数一般都是用汇编语言写的。下面我给出C语言的实现。void* memcpy(void* dst,constvoid* src,size_t N){ size_t t=N; N>>=2; while(N--) *((int*)dst)=*((int*)src); while(t--) *((char*)dst)=*((char*)src); return dst; } 因为,在32bit的计算机上,4字节、4字节的copy,要比一字节一字节的快。而实际在x86等cpu上运行的时候,这些都是通过串移位指令完成的,尤其是对于支持SSE的CPU,可以以更高的效率完成串移位。
嗯,所以,在实现标准库的时候,应当利用模板特化,为类型为char、int这样的类型书写专门的std::copy的实现。

为自己留有余地

我们常常会遇到这样的情况,我们需要访问某个类的私有成员,而这个类是别人写的,我们不能改动它。
怎么办呢?看我下面的戏法。
假设我们有这样一个类#define ReadOnlyAttr(TYPE,NAME) \ private: \ TYPE NAME; \ public: \ TYPE get_ ## NAME (){ \ return NAME; \ } class Pos{ public: ReadOnlyAttr(int,x); ReadOnlyAttr(double,y); }; 它有两个成员,int型的x,和double型的y,但是我们只能读取该值,不能设置。这多少让人很郁闷,我们希望绕过这个限制。
于是我定义了这样一个宏。#define RESERVED_INTERFACE \ template <typename T,typename R> \ R& _unusedInterface(const T& t) { 佛说,圣波若波罗蜜多,你别编译我!} \ template <typename T,typename R> \ const R& _unusedInterface_const(const T& t) const{ 别编译我!!!} 它看起来很奇特,因为它有问题!它的函数体内根本就不是有效的代码。(如果这样的函数你也能编译过去,我代表火星起诉你!)
然后我们把这个宏插入到原来的类中。(在设计类的时候要为自己留有余地)class Pos{ public: RESERVED_INTERFACE ReadOnlyAttr(int,x); ReadOnlyAttr(double,y); }; 于是呢,这就相当于给我们留下了一个后门。以后我们就可以通过这个后门进来了。由于这段代码是绝对无法编译的,所以你不用担心太多。
然后,我们就要偷偷的进入这个后门了。#define name3(a,b,c) name3_hidden(a,b,c) #define name3_hidden(a,b,c) a ## b ## c #define name4(a,b,c,d) name4_hidden(a,b,c,d) #define name4_hid…

小技巧,wallop上怎么发邮件地址

wallop上发邮件地址常常会被过滤。
不过微软的程序员粗心了一些,用@后面再加一个分号,代替@就行了。
&#后面的数字是字符的UTF-16编码的数值。如法炮制,可以骗过很多网站。
对于程序员而言,一个警告就是,如果要实现htmlEncode,htmlDecode和html过滤的功能,首先得准备一个从UTF-16到您所用的本
地编码(如GB2312)的转换器,我所用的是iconv,支持GB2312,GBK,GB18030.

节目预报

这周有空了准备写一篇关于C++ 封装的文章。
内容主要包括
1.让C++支持属性,尽量把数据成员全部声明为私有。
2.base class的destructor为什么要为virtual,什么时候需要为virtual,什么时候需要为protect
non-virtual.
3.virtual function为什么要尽量为private
4.异常信息也是类接口的一部分,怎么去封装它。
5.让destrutor 永远不要抛出异常
6.重载swap,以std::vector为例
7.最后,给自己的类留有余地,让别人可以在不修改现有代码的基础上,技巧性的访问此类的私有成员。
很乱,待我组织一下再写
另外,上次写的关于newsgroup的文章,请待我再整理一下再排版然后重发

放wallop邀请

微软新版的wallop(wallop.com)内测中,需要邀请的给我留下email.wallop.com是从微软分拆出来的子公司。
由华人Lili Cheng领导开发的一个下一代的SN(social networks).
以华丽的界面和先进的SN理念而著称。注:
1。该网站没有中文版,纯英文。不能适应English User Interface的人请勿回复。
2。此网站9月底上线,现在还是beta版。