printf( const char * fmt, ... )
{
    char buf[2048];
    va_list va;
    va_start( va, fmt );
    vsnprintf( buf, sizeof(buf), fmt, va );
    va_end( va );
    return std::string(buf);
}


posted @ 2008-07-29 14:48 micheal's tech 阅读(550) | 评论 (0)编辑 收藏

socket 为网络间通信机制 ,可以同步同一计算机的通信(127.0.0.1)或者网络上的计算机。
socket(int domain, int type, int protocol)
为常用的建立socket形式。

socket 与调用open相类似,均可获得用于输入/输出的文件描述符,当不再调用该文件描述符的时候,调用close来关闭对文件或者套接字的访问,并且释放该描述符以便重新使用。
 
虽然套接字描述符本质上是一个文件描述符,但不是所有文件描述符处理的函数都可以处理它。

大端,小端。


posted @ 2008-07-29 09:56 micheal's tech 阅读(137) | 评论 (0)编辑 收藏

四则运算包括括号一般用栈来实现。
#include "stack.h"
#include <string>
#include <iostream>
using namespace std;

int main(int argc,char *argv[])
{
    //char *a = argv[1];
   // char *a = "(((2*(3-3))+5)*3)";
    char *a = "4*3-2";
    size_t len = strlen(a);

    //the operation value
    MyStack<int> opv(128);
    //the opeartion transfer
    MyStack<char> opt(128);


    for(int i=0;i<len;i++)
    {
        if((a[i]>='0')&&(a[i]<='9'))
                //cout<<a[i];
        {
            opv.push(0);
   
        }
        while((a[i]>='0')&&(a[i]<='9'))
        opv.push(opv.pop()*10+a[i++]-'0');
        if(')'== a[i])
        {
            char c = opt.pop();
            if('*' == c)
            opv.push(opv.pop()*opv.pop());
            if('+' == c)
            opv.push(opv.pop()+opv.pop());
            if('-' == c)
            opv.push(-(opv.pop()-opv.pop()));
        }


   
        if(('-'== a[i])||('+' == a[i])||('*' == a[i]))
        {
            opt.push(a[i]);
        }
    }
    cout<<opv.pop()<<endl;


}

posted @ 2008-07-22 15:40 micheal's tech 阅读(1022) | 评论 (0)编辑 收藏

保证基类的也被调用。什么情况下使用比较好呢。

#include <iostream>
using namespace std;
class Base{
    private:
        int num1;
    public:
        Base():num1(10)
        {
        }
        virtual ~Base()
        {
            cout<<"base"<<endl;
        }
};
class Dervied:public Base{
    private:
        int num2;
    public:
        Dervied():num2(1)
        {
        }
        ~Dervied()
        {
            cout<<"Dervied"<<endl;
        }
};
int main()
{
    Base *pBase = new Dervied();
    delete pBase;
}

结果会
Dervied
Base
#include<iostream>
using namespace std;

class ClxBase
{
    public:
       ClxBase() {};
       ~ClxBase() {cout<<"Do base class destruct"<<endl;};

};

class ClxDerived : public ClxBase
{
    public:
       ClxDerived() {};
       ~ClxDerived() { cout << "Do derived class destruct!" << endl; };

};


int main()
{

    ClxBase *pTest = new ClxDerived;
    ClxDerived derived;

    delete pTest;

}
另一个例子输出的却是 :
Do base class destruct
Do derived class destruct!
Do base class destruct

说明了两个问题,只想派生类对象的基类指针需要基类声明虚系构函数才能调用派生类指针,而派生类对象却不用基类声明虚系构函数就能调用派生类指针


posted @ 2008-07-08 17:10 micheal's tech 阅读(272) | 评论 (0)编辑 收藏

“从程序员的角度来看,STL是有一些可适应不同需求的群集类别(collection classes),和一些能够在这些数据群集上运行的算法构成。”

“当然,如此灵活性并非免费午餐,代价总是有的。首要的一点是,STL并不好懂。”(这是一场持久仗啊)

“若干精心勾画的组件共同合作,构筑起STL的基础。这些组件中最关键的是容器、迭代器和算法。”

“容器 Container,用来管理某类对象的集合。”

“迭代器Iterators,用来在一个对象群集的元素上进行遍历动作。”

“算法 Algorithms,用来处理群集内的元素。”

“STL的基本观念就是将数据和操作分离。数据由容器类别加以管理,操作则由可定制的算法定义。迭代器在两者之间充当粘合剂,使任何算法都可以和任何容器交互运作。”

在标准库中,容器分为:序列式容器、关联式容器。

序列式容器:可序群集,其中每个元素均有固定位置—取决于插入时机和地点,和元素无关。如果以追加的方式对一个群集置入六个元素,它们的排列次序和置入次序一致。有几个已定义好的容器:vector、deque、list。

关联式容器:以序容器。元素位置取决于特定的排序准则。如果将六个元素的置入这个群集中,它们的位置取决于元素值,和插入次序无关。也就是说,关联式容器可以自动排序。STL提供了四个关联式容器:set、multiset、map、multimap。

 

//stl/vector1.cpp

#include<isotream>

#include<vector>

using namespace std;

 

int main()

{

   Vector<int>coll;

   //append elements with values 1 to 6

   for(int i=1;i<=6;++i)

          coll.push_back(i);

  

   //frint all elements followed by a space

   for(int i=0;i<coll.size();++i)

          cout<<coll[i]<<’’;

   cout<<endl;

}

这是一段利用vector的函数,将6个元素插入到vector中的代码。一边输入这些代码,一边感叹STL的强大。想想当初学数据结构时那些算法,当然STL的功能绝不是这么简单的。代码重用性得到了很大的提高。

需要注意的是,STL只提供时间效能良好的成员函数,时间效能良好通常意味具有常数复杂度或者对数复杂度。

简单说说关联式容器。

Sets:set内的元素依据其值自动排序,每个元素只允许出现一次,不允许重复。

Multisets:和set相同,只不过它允许重复元素。

Maps:它的元素都是“实值/键值”所形成的一对数。每个元素有一个键,是排序准则的基础。每一个键只能出现一次,不允许重复。

Multismaps:和map相同,但允许重复元素。

容器配接器:

除了以上数个根本的容器类别,为满足特殊需求,C++标准程序库还提供了一些特别的(并且预先定义好的)容器配接器,根据基本容器类别实作而成。包括:Stacks(LIFO)、Queues(FIFO)、Priority Queue。

posted @ 2008-06-30 17:40 micheal's tech 阅读(190) | 评论 (0)编辑 收藏

内部排序的几种方法的比较
                       最坏时间复杂度  平均时间复杂度  空间复杂度   稳定排序  其它特点
冒泡排序
快速排序

插入排序
shell排序

选择排序
堆排序

归并排序

基数排序
http://student.zjzk.cn/course_ware/data_structure/web/paixu/paixu8.7.1.1.htm


posted @ 2008-06-27 16:01 micheal's tech 阅读(251) | 评论 (0)编辑 收藏

学员换人程序,学员换人要作到车尾下车右则绕,绕到左门喊报告。
  上车程序,打开车门要问好,右手扶手,左手门,左腿踏板右腿到,注意要把门关牢,调整座位来报到,左腿离合右腿油,轰声空油报仪表(考官同意起步走)。转向灯,后视镜,踏离合挂(一挡,二挡)。
  上坡起步,油离配合放手刹,手刹跟着油门下。下坡起步,转向灯,后视镜,踏离合挂(一挡,二挡)注意要把手刹先放下,油离配合跟油走,达到平稳起步的目的。
  上坡行驶,要想加挡先加速,加速在先,加挡在后。要想减挡先减速,减速在先,减挡在后。
  下坡行驶,起步后,要跟油走,连续加挡不加油。要想减挡先减速,减速在先,减挡在后。
  路面行驶总结一句:根据不同的路面情况,选择不同的车速,根据不同的车速,选择不同的挡位,拉开前后车的安全距离,达到安全平稳行驶的目的。
  路口行驶,进入路口之前三十米,减速选挡,观察路口情况,听从教练口令,抓住时机,随车尾通过,不能迎车头走,随车尾通过体现让行,顺利通过。迎车头体现抢行,两车相遇,违章在先。
  通过障碍,单边双边和井盖要注意自己的左膝盖。
  苜蓿叶桥,教练发出右转弯直接右转上引桥,教练发出左转以两个右转达到调头目的,交叉路不准转弯。环岛桥看做是环岛逆时针方向绕环岛。不同的是环岛中间有条直行道,环岛四周有引桥,环岛桥分成四等份90度右转180度,直行270度,左转360度调头。
  环岛,以逆时针方向绕环岛进左,出右调头左转走里,直右走边,找路号。
  弯道行驶,上坡转弯,弯前减速选择挡位,打方向弯中加油回方向,回正方向根据情况变换挡位,跟油走。下坡转弯,弯前减速带着刹车打方向回正方向,根据情况变换挡位直行走。
  上坡行驶中,教练发出停车令,转向灯后视镜,作到选择挡位,跟油走,调整方位右,左,右靠边要把车放正,收油门备刹车,代刹车的同时,切断离合,再利用刹车控制速度到停车,拉手刹挡摘下,转向灯回位,抬离合放刹车,停车完毕。
  下坡行驶中,教练发出停车令,转向灯后视镜,带着刹车,调整方位右,左,右靠边要把车放正,切断离合再去刹车,达到平稳停车,拉手刹挡摘下,转向灯回位,抬离合放刹车,停车程序完毕。

posted @ 2008-06-27 15:44 micheal's tech 阅读(86) | 评论 (0)编辑 收藏

#include <iostream>
using namespace std;
int getIndex(const char * p,int next[])
{
    if(p == NULL)
        return -1;
    int k = -1;
    int j = 0;
    next[0] = -1;
    while(p[j])
    {
        if(k==-1||p[k]==p[j])
        {
            ++j;
            ++k;
            if(p[k]!=p[j])
            {
                next[j] = k;
            }
            else
            {
                next[j] = next[k];
            }
        }
        else
        {
            k = next[k];
        }
    }
}


int kmpcompare(const char * srcstr,const char * deststr,int next[] )
{
    if(!srcstr ||!deststr||!next)
        return -1;
    int i = 0;
    int j = 0;
    while(srcstr[i]!='\0'&&deststr[j]!='\0')
    {
        if(srcstr[i] == deststr[j])
        {
            i++;
            j++;
        }
        else
        {
            if(next[j]!=-1)
            {
                j = next[j];
            }
            else
            {
                i++;
                j=0;
            }

        }
    }
    if(deststr[j] == '\0')
    {
        return i-j;
    }
    else
    {
        return -1;
    }

}




posted @ 2008-06-26 17:37 micheal's tech 阅读(197) | 评论 (0)编辑 收藏

摘 要: 与常见的数据库相比,嵌入式数据库具有体积小、功能齐备、可移植性、健壮性等特点,本文分析和比较了典型的嵌入式数据库SQLite和Berkeley DB。首先从体系结构、子系统间调用关系、任务执行过程等角度对SQLite和Berkeley DB进行了详细分析,然后重点从数据类型、存储方式、模式、数据库引擎和错误处理及加密功能等方面讨论了SQLite和Berkeley DB的异同点,最后列举了一个基于ARM—Linux的SQLite应用实例。
关键词: SQLite、Berkeley DB、SQL、虚拟数据库引擎(VDBE)


引言

随着计算机技术与其它学科间的不断交融、渗透,数据库应用的范围更加深入和具体。那些仅适用于PC机,体积庞大、延时较长的数据库技术已不能满足针 对性较强的嵌入式系统开发的需求。SOLite和Berkeley DB是目前应用较广泛、技术较稳定的两种嵌入式数据库。然而,国内对嵌入式数据库的研究起步较晚,还没能引起更多人的关注。更多人熟悉那些基于C/S或B /S结构的关系型数据库来实现数据的存储、检索等功能。然而,在嵌入式系统中,由于软硬件资源有限,不可能安装庞大的数据库服务器,而用户的需求可能由一 个简单的基于磁盘文件的数据库系统就能实现,这仅仅是利用了那些数据库的基本特性。此时,对嵌入式数据库的研究就显得尤为重要了。

1嵌入式数据库

嵌入式数据库通常是与嵌入式操作系统及具体的应用集成在一起,无需独立运行数据库引擎,由程序直接调用相应的API就可实现对数据的存取操作。嵌入式系统的开发环境决定了其数据库的特点:

1、  体积适当

由于嵌入式系统自身的特点,对数据的存储和程序的运行都有较强的空间限制,所以嵌入式数据库首先应该保障的就是适当的体积。进一步来说就是占用尽量少的ROM、RAM及CPU的资源。

2、  功能齐备

嵌入式系统开发中,用户需求决定了需要一个大小适中、功能齐备的数据库来实现数据

管理,这就使得开发人员要采用一个能够提供完备开发文档且易于开发的数据库技术。此外,

国家863项目2002AA714023,研究生精品课程资助05531451

在嵌入式设备中,数据库的管理对用户来说是透明的,这就要求此数据库能够自动完成启动初始化、日志管理、数据压缩、备份、数据恢复等功能;而且嵌入式设备经常有不可预料的硬复位,这就需要此数据库有高度的健壮性。

3、  可移植性

嵌入式系统的平台种类繁多,因此嵌入式数据库应有一定的可移植性,以适用于不同的软硬件平台。

4、代码开源

开源的代码在产品的开发过程中不仅可以减少开发成本,更重要的是为后期的维护完善和稳定运行都提供了最为彻底的解决方法。

2 SQLite

    SQLite是D.理查德.希普用一个小型的C库开发的一种强有力的嵌入式关系数据库管理体制。虽然功能较Berkeley DB稍显逊色,但它简单易学、速度较快,同时提供了丰富的数据库接口,提供了对SQL92的大多数支持:支持多表和索引、事务、视图、触发和一系列的用户 接口及驱动。

    SQLite的体系结构大体上可以分成八个主要的子系统,如图1所示。对数据库进行的各种操作都是按照此顺序,逐一执行的。顶层是标记处理器 (tokenize)和分析器(parser)。SQLite有自己高度优化的代码生成器,可以快速、高效地生产出代码。底部是经过优化的B树,这样有助 于运行在可调整的页面缓冲上时,对磁盘的查找降低到最小。再往下是页面高速缓存,它作用在OS的抽象层之上,这样的体系结构使数据库的可移植性变为可能。

    该体系结构的核心是虚拟数据库引擎(VDBE)。VDBE完成与数据操作相关的全部任务,并且是客户和存储之间信息交换的中间单元。从各个角度分析,它都 是SQLite的核心。当SQL语句被分析后,VDBE便开始工作。代码生成器将分析树翻译成一个袖珍程序,随后这些袖珍程序又被组合成VDBE的虚拟机 器语言表示的一系列指令。如此反复,VDBE执行每条指令,最终完成SQL语句指定的查询要求。

    SQLite有以下特性:支持ACID事务、零配置―无需安装和管理配置、存储在单一磁盘文件中的一个完整的数据库、数据库文件可以在不同字节顺序的机器 间自由共享、支持数据库大小至2TB、足够小、全部源码大致3万行C代码,250KB、比目前流行的大多数据库运行速度快,提供了对事务功能和并发处理的 支持、应用Transaction既保证了数据的完整性,也会提高运行速度,因为多条语句一起提交给数据库的速度会比逐一提交的方式更快、独立、没有额外 依赖。

3 Berkeley DB

Berkeley DB是由sleepycat software开发的轻量级嵌入式数据库,它不仅适用于嵌入式系统,而且可以直接连接到应用程序内部,和应用程序运行在同一地址空间。传统的数据库一般 作为独立服务器工作,而Berkeley DB是软件开发库,开发者将它嵌入到应用程序中,应用程序本身就是一个服务器,而只是利用嵌入式数据库开发来实现定制的数据库逻辑,避免了与应用服务器进 程间通信的开销,因此Berkeley DB具有较高的运行效率,适用于资源受限的嵌入式系统。

一般而言,Berkeley DB数据库系统可以大致分为五个子系统,如图2所示。

1、  存取管理子系统(Access Methods)

该子系统为创建和访问数据库文件提供基本的支持。在没有事务管理的情况下,该子系统中的模块可单独使用,为应用程序提供快速高效的数据存取服务。

2、  内存池管理子系统(Memory Pool)

该子系统就是Berkeley DB所使用的通用共享内存缓冲区,该子系统可以被应用程序单独使用。

3、  事务子系统(Transaction)

该子系统为Berkekey DB提供事务管理功能,保证操作的原则性、一致性和孤立性。事务子系统适用于对需要事务保证的数据进行修改的场合。

4、  锁子系统(Locking)

该子系统提供进程之间以及进程内部的并发管理机制,为系统提供多用户读取和单用户修改同一对象的共享控制。该子系统可以被应用程序单独使用。

5、  日志子系统(Logging)

该子系统采用的是先写日志的策略,支持事务子系统进行数据恢复,保证数据一致性。

 

4、SQLite与Berkeley DB的异同

   通过上面的一些介绍,也许会对SQLite和Berkeley DB有了一定的了解。从目前的趋势看,这两款嵌入式数据库有着旺盛的生命力,较好的应用领域及发展空间。笔者翻阅了大量的资料,从各个角度,对它们的异同进行了多方面,多层次的比较,如表1所示。

表1 SQLite与Berkeley DB的异同


特性

SQLite
Berkeley DB

是否为关系数据库

是否支持SQL

开发语言

数据类型

存储方式

存储模式

数据库引擎

适用系统

 

错误处理

加密功能

是否免费

难易程度

C语言

转换成ASCII码

Btree

虚拟

从ARM/Linux到SPARC/Solaris多种硬件平台

较少

全部

较易

C、Java语言

原样存储

Btree、Hash、Queue和Recno

UNIX/POSIX systems、Win32及嵌入式系统WinCE、VxWorks等

较详细

部分

较难


 

通过此表我们可以较为直观地看到,SQLite和Berkeley DB在数据库类型、开发语言、存储方式、模式等方面有着较大的差异。下面笔者就对其中某些重要方面进行相对详细的论述:
1、  数据库类型

SQLite基于关系数据库模式,支持绝大多数标准的SQL92语句,在很大程度上实现了ANSI SQL92标准,特别是支持视图、触发器、事务,支持嵌套SQL。它通过SQL编译器(SQL Complier)来实现SQL语言对数据库进行操作,采用单文件存放数据库。在操作语句上更类似关系型数据库的产品使用,非常方便。这也就使得那些曾经 有过PC机数据库经验的人,对SQLite的学习变得易如反掌。

此外,SQLite也有API的概念,而且极其易于使用,只需要三个用来执行SQL和获得数据的函数。它还是可以扩展的,允许程序员自定义函数,然 后以callback的形式集合进去。C语言API是脚本接口的基础,如已经发布的(Tcl接口)。开放源码团体已经扩展了众多的客户接口、适配器、驱动 等,这就使得其他语言对SQLite的使用也成为可能。

Berkeley DB不是关系型的数据库,不能应用标准的SQL语句对数据库操作,对它的操作要调用专用的API实现。这些API提供了查询、插入、删除等功能。使用 Berkeley DB提供的函数来进行数据库的访问和管理并不复杂。在大多数场合下,只需按照统一的接口标准进行调用就可以完成最基本的操作。

2、  存储方式及模式

SQLite只提供了Btree存储数据的模式。对二进制数据,SQLite不能直接保存;但可以先将二进制的数据转换成ASCII编码,然后再保 存。Base64编码机制是最常见的把二进制数据转换成ASCII编码的手段。在SQLite的C语言代码encode.c中,提供了Base64编码的 功能。

Berkeley DB对任何存入的数据都是按原样直接存储到数据文件中去,无论其是二进制数据还是ASCII或Unicode等编码的文本。Berkeley DB提供了四种存储数据的模式:Btree、Hash、Queue和Recno。在打开数据库的时候,要指定一种存储模式。

对于以上各种存储模式的具体定义、优缺点、及适用范围,由于篇幅有限,在此就不过多叙述,如有需要可参阅相关资料。

3、  数据类型

SQLite最大的特点在于其数据类型为无数据类型(typelessness)。这意味着可以保存任何类型的数据到所想要保存的任何表的任何列 中,无论这列声明的数据类型是什么。虽然在生成表结构的时候,要声明每个域的数据类型,但SQLite并不做任何检查。开发人员要靠自己的程序来控制输入 与读出数据的类型。这里有一个例外,就是当主键为整型值时,如果要插入一个非整型值时会产生异常。

虽然,SQLite允许忽略数据类型,但是,仍然建议在Create Table语句中指定数据类型,因为数据类型有利于增强程序的可读性。另外,虽然在插入或读出数据的时候是不区分类型的,但在比较的时候,不同数据类型是有区别的。

在Berkeley DB中关键字(key)和数据(data)是用来进行数据库管理的基础,由这两者构成的key/data对,组成了数据库中的一个基本结构单元。通过使用 这种方式,用API函数访问数据库时,只需提供关键字就能够访问到相应的数据。关键字和数据在Berkeley DB中都是用一个名为DBT的简单结构来表示的,它的作用主要是保存相应的内存地址及其长度。

5 应用

SQLite嵌入式数据库提供了以源码发布的方式,要在众多的硬件平台进行移植,可以根据不同平台对源码进行交叉编译来实现。编译主要有以下几个步骤:

1、到http://www.sqlite.org/的cvs中下载最新的源代码包,解压后将生成sqlite目录,另外新建并转到一个与sqlite目录平行的同级目录,如make目录。

2、用“echo$PATH”命令查看PATH中是否已经包含交叉编译工具arm-linux-gcc。

3、为了在ARM-Linux下能正常运行sqlite,需要对sqlite/src/sqliteInt.h作一定的修改,以确保btree(B 树)有正确的变量大小,如“ptr”和“char”。不同体系结构的Linux,如X86和ARM,会有些差别。对于ARM-Linux可以找到如下部 分:

# ifndef INTPTR_TYPE

# if SQLITE_PTR_SZ==4

# define INTPTR_TYPE int

# else

# define INTPTR_TYPE long long

# endif

在上面的代码前加上一句

# define SQLITE_PTR_SZ 4

这样后面的“typedef INTPTR_TYPE ptr;”就是定义的“int”类型,而不是“long long”。

4、使用configure进行一些配置。修改sqlite目录下的configure,让configure不去检查交叉编译环境。由于篇幅有限不再详述。

5、修改Makefile文件。将代码行BCC=arm-linux-gcc-g-O2改成BCC=gcc-g-O2。另外,一般是以静态链接的形 式将sqlite放到ARM-Linux的硬件板上运行的,所以继续修改Makefile,找到标记为sqlite:的代码段,将其中的 libsqlite.la改成.libs/libsqlite.a。做完上述修改,用make生成sqlite、libsqlite.a、 libsqlite.so。为了减小执行文件大小可以用strip处理,去掉其中的调试信息。

6、在ARM板上运行sqlite。将sqlite拷贝到ARM板上,方法很多,需要根据具体的情况来选择。如ftp、cm-dftp、wget等。将sqlite下载到ARM板的/tmp目录,因为此目录是可写的。修改权限并运行:

chmod+wx sqlite

./sqlite test.sqlite

会出现

       sqlite>

如果一切正常,现在sqlite已经在ARM-Linux下跑了起来,然后就可以基于此进行下一步的应用开发了。

6 结语

嵌入式数据库SQLite和Berkeley DB,在体积上、功能上、运行速度及难易程度都存在着或多或少的异同。但它们都有能够充分适应硬件的能力,能很好地适应嵌入式系统的需要。就笔者来 看,SQLite功能虽不及Berkeley DB强大,但它的设计思想是小型、快速和最小化的管理。这就使得SQLite在大小和功能之间找到了一个理想的平衡点,而且完全的开源代码使其可以称得上 是理想的“嵌入式数据库”。当然在具体的嵌入式应用中可以根据具体情况选择应用。

参考文献:

1、http://www.sqlite.org , SQLite的官方主页

2、http://www.sleepycat.com ,Berkeley DB的官方主页

3、Michael Owens. Embedding an SQL Database with Sqlite. Linux Journal,2003 06 01

4、薛启康.Linux环境下的数据库.中国计算机报,2001总期号:1009

5、张孝.嵌入式移动数据库的现状及发展[J/OL]. http://www.basesoft.com


posted @ 2008-06-24 10:00 micheal's tech 阅读(1115) | 评论 (0)编辑 收藏

linux 出错处理
  常用的内容如下:
  l <assert.h>中支持assert()函数,注意,assert()检查发现条件不成立时调用abort()终止程序执行,应用程序没有机会做清除工作。
  l C标准定义了__LINE__和__FILE__宏,GNU C扩展中定义了__FUNCTION__宏。
  l <errno.h>中定义了errno,注意没有函数会将errno清零,所以在调用可能设置errno的函数之前先将errno清零。
  l <stdlib.h>中定义了abort()、exit()和atexit()函数。
  l 函数abort()将导致程序异常终止,在终止前程序没有机会执行atexit()登记的函数,也没有计划执行一些常规的清除工作。同时,abort()还会产生core dump,如果没有ulimit限制的话。
  l 函数exit()和abort()类似,但它在完成清理工作之后才终止程序。
  l 函数atexit()登记在程序正常终止时要调用的函数。
  l <stdio.h>中定义了perror(),<string.h>中定义了strerror()。
  l <syslog.h>中定义了syslogd的接口。


同样的情况下,windows下错误用的是getlasterror( )

posted @ 2008-06-19 15:24 micheal's tech 阅读(186) | 评论 (0)编辑 收藏

仅列出标题
共8页: 1 2 3 4 5 6 7 8