分类 技术志 下的文章

又获Ubuntu 7.10光盘

Mark Shuttleworth,Ubuntu的创始人,给了Ubuntu爱好者一个免费获取Ubuntu光盘的机会,自从去年年初收到一次Ubuntu 5.10的光盘后,昨天我又拿到了最新的Ubuntu 7.10的光盘。

去年的光盘数目很多,估计当时的Canonical是为了扩大自己的linux distribution的影响,在"shipit"页面上鼓励你多多索取光盘。也正如Canonical所期望的,我将大部分光盘都分给了周围的同事和朋友了,也算帮Ubuntu进行了一次"推广"工作了:) 而这次我申请光盘时,其网站上提供的标准选择就是一张PC CD和一张64-bit PC CD了。当然你也可以选择索取更多,但是页面上会提醒你索取非标准选项的光盘数目,邮递周期会长达6-10 weeks。我选择了标准选项。从提交订单到拿到光盘,好像只用了3 weeks的时间。


Ubuntu包裹(包裹中有ubuntu logo的贴纸)

Ubuntu 7.10光盘被设计成为了LiveCD,就是说你可以不用安装linux就可以从CD启动使用Ubuntu linux。方法很简单:将光盘放入光驱,重启computer,注意BIOS设置中要将光盘驱动器放到启动设备列表的最前面。Ubuntu光盘启动后界面和XP很相似,黑底屏幕中央一个Ubuntu的logo以及闪烁的进度条。由于需要将光盘映像读入内存,所以这个过程比较慢。等Ubuntu的桌面展现在你的面前时,你就可以试用Ubuntu了,浏览网页、编辑文档等等均可以做到,所以试用后你再决定是否要安装Ubuntu也不为晚也。


Ubuntu LiveCD引导界面


Ubuntu内核加载(与WinXP启动界面形似吧)


Ubuntu桌面 (点击桌面上的install图标即开始安装Ubuntu)


贴上Ubuntu标签的本本

面对'错误'的抉择

大凡写程序者,都会遇到错误;
大凡写程序者也都知道两种错误处理的机制:传统的'错误码返回机制'和'面向对象语言引入的异常处理机制'。

人们常常会在这两种机制之间徘徊不定,难以抉择。但有两类人大可不必为此头痛,他们是坚决只使用'错误码返回机制'的人,和坚决只使用'异常处理机制'的人。而苦就苦了摇摆在中间,思索不定的那些人了。这群人有一个特点就是不停的问:"什么是异常?什么时候该使用错误码返回?什么时候又要用标准的异常处理机制呢?内存不足是不是异常?网络瘫痪是不是异常?用户输入id的超出了允许的长度该如何处理?"等
等诸如此类的问题。

我一直使用C,C没有像C++、Java、Ruby那样提供标准的异常处理机制,C只是提供了setjmp和longjmp这样的粗糙的甚至让很多新人觉得迷惑的调用接口,所以到目前为止,我还没有真正用过"异常处理"来写过代码。直到我看到"David Hanson "的"c interfaces and implementations(C语言接口与实现)"中第4章封装的C的异常处理宏。看完后我有些迷惑。迷惑的不是这组宏有什么精湛技艺,而是他破坏了以前我对错误处理的单一使用错误码返回的想法,他又给了我一个选择:使用异常处理。而多了一种选择之后,我也陷入徘徊不定中。只能反复的一遍又一遍的看和回味Hanson在这章起始的那段关于错误分类的描述和理解,以寻求在返回错误码和使用异常处理之间的平衡。

Hanson将错误分为三类:
用户错误,就是由用户的不正确输入引起的,对于此类错误的态度是:函数必须处理错误并返回错误代码。
//testusererr.c
int main(int argc, char *argv[]) {
if (argc <= 1) {
printf("you should input at leaset an argument!\n");
return 1;
}

int i = atoi(argv[1]);

if (i < 5) {
printf("i should be more than 5.\n");
return 2;
}

return 0;
}

上述的例子仅是一个程序接收用户的输入,并对其输入错误进行处理。

那么对于一个功能接口而言,对其参数是否都要做类似处理呢?通常来说在我们系统中除了针对用户的接口需要进行外,其他的接口都是内部调用的,比如库,库提供了接口同时也隐含了某种约定。我们作为程序员在使用库的时候都会遵守约定。但是这是不是这些库接口就不用对其接口参数进行任何处理了呢。一般我们会在接口的入口处加上断言。这就是我们要说的第二种错误–可检查的运行时错误。

按照Hanson的说法,可检查的运行时错误不是用户错误,上面已经说了,程序员已经按照约定传入了适当的参数,那么一旦出现错误,这个错误是从何而来的呢?可检查的运行时错误恰恰是揭示了程序的漏洞,他们不可预料,通常遇到此类错误,应用程序一般将无法恢复。看下面的例子:

//testcheckedrterr.c
#include
#include

#define MY_MAGIC 0×19210723

struct Foo {
int i;
char id[22];
#ifdef _DEBUG
unsigned int magic;
#endif

};

void check_foo(const struct Foo *foo) {
assert(foo != NULL);
#ifdef _DEBUG
assert(foo->magic == MY_MAGIC);
#endif
;
}

int main() {
struct Foo foo;
foo.i = 13;
#ifdef _DEBUG
foo.magic = MY_MAGIC;
#endif
strcpy(foo.id, "this will cause an overflow");

check_foo(&foo);
}

gcc -D_DEBUG -g *.c
执行的结果:
Assertion failed: foo->magic == MY_MAGIC, file testcheckedrterr.c, line 20
退出 ((主存储器)信息转储)

这里程序的确是按照check_foo的需要的参数提供了参数,只是没有预料到,程序存在栈溢出,对于这种运行时错误,在check_foo中我们使用了断言。断言一般都是无法恢复的,直接的结果就是程序退出。

异常,第三类错误,极少出现,可能不可预测,但有可能从中恢复的错误。如:内存不足、网络瘫痪、磁盘空间满等。按照Hanson的经验,由于异常发生很少,很多可能发生此类异常的函数都是没有返回值的。这时是采用异常处理机制的好时机。

说到这,也许还只是停留在说教上,也许开头提到的那些疑问仍然无法回答。我想什么样的回答都不能令所有人满意,自己在项目中摸索理解吧。其实永远没有绝对的事情,你大可在程序中丝毫不考虑使用异常机制。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats