使用rake编译C程序

Posted on 五月 20th, 2010 in 备忘 | No Comments »

每次修改代码一般只会涉及一部分文件,大部分代码都是不必重复编译的。而且编译明显是分步骤也有依赖关系,比如要测试程序就得先链接出一个可执行文件,要链接就得先编译成.o。。。所以就有了make,自动分析任务的依赖关系,只对有变更的文件执行编译,省心省时间。

不过make的语法晦涩啊…就有了rake

rake提供了file函数可以指明文件的依赖关系,比如:

file 'fdict.o' => ['src/fdict.c', 'src/fdict.h'] do
  sh 'gcc -Wall -c src/fdict.c'
end
file 'test.o' => ['src/test.c'] do 
  sh 'gcc -Wall -c src/test.c'
end

file就是个ruby的函数调用,把重复的东西去掉很简单

CFlags = '-Wall'
 
[
  ['src/fdict.c', 'src/fdict.h'],
  ['src/test.c']
].each do |fn_c, *_|
  fn_o = File.basename(fn_c).ext('o')
  file fn_o => [fn_c, *_] do
    sh "gcc #{CFlags} -c #{fn_c}"
  end
end

再就是链接和执行

OFiles = %w{fdict.o test.o}
 
task :run => [:link] do 
  sh "./test"
end
 
task :link => OFiles do
  sh "gcc #{CFlags} #{OFiles.join(' ')} -o test"
end

每修改两行C程序到控制台下边一个rake run就可以立即执行,这一来写c就有点像写脚本了。

随记

Posted on 五月 18th, 2010 in 笔记 | 2 Comments »

无论何时,只要单个资源需要在多个用户间共享,就必须处理一致性的问题。
回头想下“函数式语言无副作用适合写并发程序”之类的说法,只是在计算上的并发,对存储上的并发照样得上锁上钥匙。

win32的窗体使用handle而不是指针
一个窗体可能会被多个进程处理,也可以隐藏窗体对象的内部实现。

真空管和三极管的共性
都可以将信号放大,这一来就可以用电信号来控制开关了。就有了逻辑电路…

lua从堆栈机转到寄存器机
因为lua实现里表示值的那个结构体Tvalue是个tagged union,个头太大了(两个指针这么长)。在堆栈上push/pop一来一回吃资源,搞成寄存器机可以省些搬运。

为什么要有链接器
可以把程序分成模块。

C中结构体不可比较
因为结构体里数据对齐的空隙里面的东西可能随机的。

C++为什么不用printf
类型不安全。像cout好像是对每个内置类型都重载了一个<<操作符

x86实模式的逻辑地址
x86实模式的逻辑地址是段寄存器(如cs)里存一个基地址(16位),左移四位再加上一个16位的偏移。
为什么要这么蛋疼,因为当时的主线有20位(可寻址1mb),但是intel的寄存器只有16位。

自动机
就是根据输入自动切换状态的计算模型。不过状态有限,识别的语言(语言就是字符串的集合)是最少的。自动机可以识别的语言就叫正则语言。
给自动机加一个堆栈就是下推自动机,这样状态就可以无限了,可以识别的语言就叫上下文无关语言。
给自动机加一个随机存储,就是图灵机了。可以识别的语言就叫可判定语言。

rails使用paperclip插件上传时遇到500 Internal Server Error

Posted on 五月 11th, 2010 in 备忘 | 18 Comments »

有可能是imageMagick没装利索。找不到imagemagick,显示错误信息的时候试图把上传的文件对象序列化,就505了。

sudo apt-get install imagemagick --fix-missing

使用三方库就得做好不可预料事件的准备哇

关于paperclip的使用,这两篇简介好像不错:
http://jimneath.org/2008/04/17/paperclip-attaching-files-in-rails/
http://thewebfellas.com/blog/2008/11/2/goodbye-attachment_fu-hello-paperclip

ps: 又遇到了个没预料的问题,上传validates_attachment_content_type指定的类型之外的文件时候同样会遇到个500 internal server error,未解中。

踩踩数据结构什么的 =“=

Posted on 五月 8th, 2010 in 备忘 | 5 Comments »

发觉算法太弱了 =”=

当年在ACM那里呆了两天就隐身了,可惜那个老师非常非常非常好的(实验室里还有空调 >_<)。总觉得这玩意水太深,掉进去就出不来了....“不成熟的优化乃万恶之源”这话又正好应了惰性心理,心安理得地“出了性能问题再说之前先弄出来再说管算法干嘛”...可现实往往是,不会算法你压根就弄不出来...

先从一棵二叉查找树开始好了。挖坑慢慢填,时间有的是(?)

module BTree where
 
data BTree a b = Empty 
               | BNode {
                    kv :: (a, b), 
                    left :: BTree a b,
                    right :: BTree a b
               } 
               deriving(Show, Eq)
 
insert :: (Ord a) => (a, b) -> BTree a b -> BTree a b
insert (k,v) Empty = BNode (k, v) Empty Empty
insert (k,v) pnode@(BNode (pk, _) lnode rnode) 
    | k == pk   = pnode { kv = (k,v) }
    | k <  pk   = pnode { left  = insert (k,v) lnode }
    | k >  pk   = pnode { right = insert (k,v) rnode }
 
find :: (Ord a) => a -> BTree a b -> Maybe b
find k Empty = Nothing
find k (BNode (pk,pv) lnode rnode)
    | k == pk = Just pv
    | k <= pk = find k lnode
    | k >  pk = find k rnode
find _ _ = Nothing
 
remove :: (Ord a) => a -> BTree a b -> BTree a b
remove k Empty = Empty
remove k pnode@(BNode (pk,pv) lnode rnode) 
    | k == pk = merge lnode rnode
    | k <= pk = pnode { left = remove k lnode }
    | k >  pk = pnode { right = remove k rnode }
 
merge :: (Ord a) => BTree a b -> BTree a b -> BTree a b
merge lnode rnode = fromList $ (toList lnode) ++ (toList rnode)
 
--helper
isEmpty Empty = True 
isEmpty _     = False
 
fromList :: (Ord a) => [(a,b)] -> BTree a b
fromList = foldl (flip insert) Empty 
 
toList :: BTree a b -> [(a,b)]
toList Empty = [] 
toList (BNode (k,v) lnode rnode) = 
    (toList lnode) ++ [(k,v)] ++ (toList rnode)
 
-- for test
root = fromList $ [
    (4, "fleurer"), 
    (10, "ssword"), 
    (100, "ssword"), 
    (2, "xx")]

haskell做数据结构好像别扭的很…不用ST Monad或者IO的话什么都是值还不能引用,像二叉树的旋转什么的就没想出常数时间的办法。像上面那个remove就直接简单粗暴了orz

(邪恶音:用ST Monad不就好了嘛)
(ST Monad都用了还用haskell干嘛 TvT)

blah~

Posted on 五月 7th, 2010 in 杂碎 | 4 Comments »

“好久没更新了”~orz又这么开头了。

昨天下午给新人讲东西时候差点着起急来,耐心什么的实在是差了些。同理,这个blog也快不会写了。笔记什么的都有记在在本子上,怨念什么的也都在twi上发泄了个精光。想翻译点东西可是怎么都觉得驴唇不对马嘴,就全部作罢。

完整的橇课,上午看书下午敲代码。再同各种善意的小朋友交流下,要说充实倒确实非比寻常。不过总觉得倦的厉害,简单一个“中午不睡下午崩溃”似乎还说不过去。代码就够傲骄了,人自然更难伺候。写这句话的时候当年推销饮水机的两位童鞋又敲门进来推销凉席,都不容易。

还是说代码吧。敏捷编程什么都领悟不了还扯淡什么人生。一天几十行,我起草一份《蜗牛宣言》好了~

想用rails换掉学校网站正在用的这个aspx系统。都说rails不好维护,可是当前的这aspx系统我已经完全维护无力了,瞅着bug在那里只能对着那两万行的一个类发呆。用rails重写最起码我能维护,能用不能用写出来再说。(敏捷什么的就当笑话听吧)

闲着把寒假时候烂掉的那个堆栈机完善了下,随后发懒两个星期没碰代码,回头想下应该差不多能用了(当然是想当然)。代码改的相当蛋疼,用上了ruby那VALUE式的tagged pointer,没打算oo的也在c里把类型搞成了对象,再就是大量少于十行的小函数。以前只是听说lua的upvalue实现很简洁,看了下发现用在这里不合适,lua的临时变量和求值栈都在同一个栈帧里连续着,只要不是闭包的变量在函数执行完立即回收。而这个堆栈机里的堆栈只是求值栈,临时变量都在一个动态分配的结构体里。这里让栈帧在函数执行完后统统保留,等着GC回收就是。

从淘宝上打印了本《莱昂氏unix源码剖析》,作者好个惜字如金,读起来也很吃力。 前半部分是unix v6的全部源码,仅9000行出头。随便翻下就被雷了,内存管理的malloc和mfree不到百行,而枚举一个进程的子进程什么的就都这样:

for(p = &proc[0]; p < &proc[NPROC]; p++)
if (a->p_pid == p->p_ppid) {
        p->p_ppid = 1;
        if (p->p_stat == SSTOP)
                setrun(p);
}
swtch();

简单粗暴,多好。