昨夜写的。 做手机开发有些时间了, 写这些是希望认识更多同行的朋友们,多多交流 : ) MSN: plusluo@hotmail.com    

 

     目前在沿海地区的手机市场中,智能手机的市场占有率正逐年升高,在深圳,遍街可以见到N73, S1... 不过到目前为止,也远未达到半数以上的程度,再加之内地城市以及广大的农村,智能手机还有着巨大的发展空间。未来的3G布局已经初步显现,虽然还没有正式实施,但是我相信这一次不会让大家再等太久了。

 

     智能手机普及的时代就在眼前了。在这样的大好前景下,摆在我们这些开发者面前的却有一个巨大的难题,我们来看看我们常见到或者听到的这些智能手机操作系统:Symbian, Windows mobile, IPhone, Linux, Android, Brew, Palm, MTK。数一数就有八种之多,而且这还不是全部。极少有程序员可以把他们全部精通,我们必须有所选择。选谁?这是个问题。我曾经遇到一个网友,问我们公司招聘手机开发吗?我说:招。他说他做了5年的Brew,我说你做过其他的系统吗,他说没有。我说:很可惜,我们不要Brew的开发。事实上,Brew正在死亡。也许5年前,Brew还颇有份额,但现在已经没有了未来。选错了道路,后果会很不好。不过我这里不是想要说我们应该选择谁,而是想评论一下各系统的未来的大致前景如何,真正的选择只能每个人自己来做,因为即使我估算得再好,未来仍然是不可预知的。

 

     现在智能手机操作系统最大的问题是,他们太多了,缺乏统一的标准。无故加大了程序开发者们的工作量,一款软件要适应好几种系统。就像战国时代,必须要有人出来一统江湖。那么谁又拥有成为霸主的实力?


     首先来说一下Symbian。它是目前智能手机操作系统中的大哥大,占有率最高,美誉度最高,加之诺基亚对Symbian的回购,宣布开源,前景被普遍看好。这是大众的观点,但是我却有所顾忌。事实上诺基亚买下整个Symbian并非明智之举,目前Symbian巨大的市场占有率归功于诺基亚,三星,索爱等几大巨头颇高的销量。尤其是占据第一市场份额的诺基亚,在其智能手机中清一色的采用了Symbian。所以这里有一个问题,可能是诺基亚的高层们意识不到的。诺基亚卖得好,其实并不归功于Symbian系统。更多的可能还在于诺基亚硬件的高品质,以及从低端市场就开始积累起来的手机高质量的口碑。所以Symbian其实是沾了诺基亚优秀的工业设计以及高品质的制造能力的光,从而掩盖了Symbian自身的缺憾。当其它几大厂商不再拥有Symbian的份额以后,它们也就没有了和Symbian的血缘关系,他们将可能抛弃这个其实并不好用的Symbian系统,以后的Symbian之路,可能将是诺基亚孤军奋战了。Symbian开源了,为什么还会被抛弃?其实,Symbian系统拥有很多的问题,它开发难以上手,系统性能不够强大,虽然诺基亚一再鼓吹它的强大,但事实上,如果你对Window moblie了解更多的话,就会知道,Symbian其实是多么菜的一个系统。根本就先天不足,即使后天营养再好,也难以成为天才。所以,Symbian未来的路是扑朔迷离。不过,毕竟瘦死的骆驼比马大,我预计在未来5年内,Symbian保持第一的位置还可以做到,但在5年以后,很可能将被击败。

 

     那谁将会击败Symbian,谁会是未来的黑马,这里有两个候选者:Windows mobile 和 Android。

     事实上,我更看好Android,因为Windows mobile固然强大,却也有着很严重的问题,而Android又有着太多的未知数,让人充满期待。Windows mobile作为windows的子嗣,拥有着优厚的先天条件。在人们评说智能手机操作系统时,总是会优先想到它,目前所有的手机操作系统中也只有它最容易让人感受到智能手机的概念。它的功能无疑是目前所有手机操作系统中最为强大的,也最为有发展潜质的。然而,很可惜的是。它实际的发展远不如人们预期的好。市场占有率远远的低于Symbian,也低于Linux。实际上,微软这位巨人在Windows mobile的发展上并未上心,或者说是没有全力以赴。从很多地方我们可以找到证据:
1、微软有能力让PC上的IE所向披靡,而moblie IE却几乎是我用过的最难用的手机浏览器;
2、微软几乎照搬电脑的操作习惯来做手机系统,无疑节省了不少设计的成本,却让Windows mobile怎么看也不像手机的系统,怎么也不符合手机的操作习惯;
3、Windows mobile程序的安装包至今无法支持打包中文程序,微软明知这个bug的存在却迟迟不做修改
4、早期的Windows mobile开发文档错漏百出,给开发人员带来很大痛苦。虽然后面的版本已有改进,但仍然有文档不详、不全的嫌疑。
5、就我所知的Windows mobile的smartphone版本的一些控件存在明显bug,同样也迟迟没有改正。
......  ......
在Windows mobile上,微软有太多的不认真。当然这还不是它市场占有率低下的全部原因。另外一个大的问题是Windows mobile的价格问题。Windows mobile定位自己为高端,高端当然有高价。但这是一个失败的策略。要知道,卖手机不是卖汽车。手机系统的市场迟早要天下一统的,谁的占有率最高,未来才最有胜算。当一款系统的占有率低到一定程度以后,为它开发软件的人就会开始减少,而应用软件的减少又会进一步的降低它的占有率,恶性循环之下,迟早死亡。Windows mobile的未来就在微软自己手上,认真一点就前程似锦,而维持现状,未来就难以言状。

     下面说一下Android与Linux。手机的操作系统中活跃着几十种规范不一的Linux,混乱不堪,难以壮大。虽然开发者们对Linux的免费与开源一直以来都报以极大的好感,但是它却不能成大器。Android的出现无疑是Linux的一次机会。虽然Google基于Linux内核开发的Android目前还没有真机面市,但已经被太多的人寄予厚望。全球主要的手机厂商多数都加入了Google的Android的联盟。Google的口碑与声望将注定Android是一款不同于以往所有Linux的换代产品。传闻10月份就会有Android的真机面市,我们在试目以待。不过,从与一些Android的开发者们的交流中获知,目前的Android还太不稳定,Bug还太多。毕竟它还在初生阶段,一出生就将和各大已经颇为成熟的系统竞争,所以Android的起步会有一些不平坦,但它的未来将颇为精彩,期望着它会有击败Symbian的一天。

 

     接下来就是目前风头正劲的IPhone了,苹果粉丝们的热情总是如此高昂,把IPhone的这一股流行潮吹便了世界各地。给各大手机厂商都带来了莫大的惊恐。虽然这支异军来的是突然袭击。但事实上,苹果IPhone的开发进行已久。在苹果公司内部,其计划的诞生至少远于五年以前。所以它一出现,便异常强壮,漂亮的外观,过硬的品质,极为人性化的操作。再加之苹果近来的一招:低廉的价格。更是让它所向披靡。虽然在中国,它还很贵。不过这不重要,无论苹果与中移动的谈判如何,IPhone迟早会正式进入中国,借助这个世界最大的手机消费市场,IPhone还将会有一次飞跃。当然,IPhone也有IPhone的问题。过短的待机时间以及近来的IPhone电池膨胀事件也给IPhone的完美形象画上的污点。不过,这些很快就会过去,毕竟IPhone卖的时间还不太长,苹果这个追求完美的公司肯定会在不断推出新版本的过程中修复完善,而绝不会像微软对Windows moblie的问题视而不见一样。IPhone的未来也是美好的,但是它可能无法成为手机系统界的NO1.  原因在与IPhone的模式决定它不会成为开源的系统,仅靠它自己一家厂商,它难以成为最大。也许IPhone会是五年后手机系统界的第二把交椅。

 

     现在还剩下谁? Brew, Palm?算了吧,它们已经几乎退出了竞争,如果没有奇迹出现,未来的某一天,它们会彻底消失。Brew至少我已经很久没有见过它了,而Palm偶有露脸,不过最近的一次亮相,我看见的却是Palm的机器搭载了Windows mobile的系统,很明显Palm连自己都对自己没有信心了。

 

     最后还不得不提到近段时间以来令国产手机们闻风丧胆的山寨机。而山寨机的主流方案就是MTK。这个手机界的异类出奇的成功,虽然在它出现的早期并不被业界的专家们看好。准确的来讲,我不认为MTK也算得上是操作系统,也许未来它会越来越靠近操作系统的标准。但目前为止它还只是一堆硬件加了一个嵌入式的程序而已。虽然简单,但是它在未来至少三年内,在中国以及其他一些不太发达的国家都拥有极为肥沃的生长土壤。它的高潮现在还没有到达最高点,不过长远来讲,MTK最终只会是一个盛极一时,却又相对短命的方案。他算不得真正的智能系统,也不具备成长为智能系统的潜质,它的最终归属就是在一个短暂的繁荣之后,有一个大幅度的回落,最后会稳定在拥有一定低端市场占有率的水平。MTK在最后不会是前面几大成功的系统的对手,虽然短期内它在中国的占有率还高过于windows moblie等优秀的系统。

 

     Symbian, Windows mobile, IPhone, Android,MTK 会在未来五年内占据手机市场的绝大部分份额,而五年后,他们中至少会没落一到两个,再更远,也许会和PC市场一样,会有一家独大的系统出现。


     未来是否如此,我们静观其变... ...

 

posted @ 2008-09-03 00:38 猫咪 阅读(1109) | 评论 (14)编辑

1、苹果的程序和普通的C程序一样,每一个程序必须包含main( )函数。

 

2、自己使用的类名不要使用“NS”做前缀,以免引起混淆。NS是苹果自有的类专用的,它代表NeXTStep。Mac OS
X就是在NeXTStep操作系统的基础上发展起来的,苹果公司收购了NeXT公司,此举使乔布斯(Steve Jobs)重返苹果并重坐第一把交椅。

 

3、所有类里面,顶级的是被称作“对象类”(NSObject)的类。几乎所有的你创建或使用的类都
直接或间接的是对象类的“子类”(subclass)。比如类NSWindow是类NSResponder的子类,类
NSResponder又是类NSObject的子类。

 

4、Cocoa 屏幕输入函数:
NSLog(@"Julia is a pretty actress.");
以@开通的字符串表示Objective-C的字符串

 

5、Object c包含头文件使用#import
例如:#import <Foundation/Foundation.h>

5、XCode开发的主要窗口分为两个部分:
左边一栏叫做“Groups & Files”,用来处理组成你整个程序的各个素材文件。当前这里面没有太多
内容,等后面你开始写多语言图形程序时,将在这一栏里找到图形界面程序和多语言程序需要的素
材文件。如果你要在硬盘上一一去查找分散的素材文件可能会比较麻烦,Xcode中提供了虚拟文件
夹(被称为“组”(Group))概念,素材文件被分类存放在这些Groups中,可以帮助你方便的组
织这些素材。


5、界面资源文件为nib文件,类似于Windows开发的资源编辑器。Cocoa-Controls被称作“调板”,类似于Windows开发的
资源工具箱。里面存放着可以用于你的图像界面的各种对象。把光标停留在某控件上方时便会显示改控件的类名。
选中一个对象,使用command-shitf-i就可以修改它的属性


6、创建好了窗口界面资源以后,还需要为窗口创建类:
在该窗口的nib文件界面,选择“Classes”标签页。在第一栏中你会看到“NSObject”。选择它,
并在“Classes”菜单中选择“Subclass NSObject”。创建一个类MyClass之后,回到界面编辑界面中在Classes菜单
选择"Instantiate MyClass"一项。就有了一个新的叫做MyClass的图标。这个图标代表了我们刚刚创建的类的实例。

 

7、为了关联上控件和类的消息处理联系。现在来建立界面上某控件和改类的关联:
在“*.nib”窗口中单击“Instances”标签页。按住键盘上的Ctrl键并用鼠标将“控件”
拖拽到MyClass的实例上。(千万不要使用别的方法创建关联!)一条代表关联关系的线会显示在屏幕上,
确认这条线是从按钮连到了MyClass的实例上就可以松开鼠标了。当松开鼠标,检视窗口会显示关联调板,
调板中列出了对象MyClass中可用的方法。选择正确的方法并单击“Connect”按钮来完成关联过程。
当然这些方法要在事先在MyClass中添加好

 

8、Cocoa有一个很重要的awakeFromNib函数。当窗口打开,方法awakeFromNib就会自动被调用。这个方法用来初始化窗口的状态很有用


9、字符串:
由类NSString创建的字符串被叫做固定字符串,因为它不可修改。不可以修改的字符串有什么优点?
应当说这样的字符串更容易为操作系统处理,所以你的程序也可以更快的运行。
NSString * foo;
foo = @"Julia!";
有时你确实要修改它们。你可以使用另外一个类——NSMutableString
NSMutableString *foo;
foo = [@"Julia!" mutableCopy];
[foo appendString:@" I am happy"];
,方法mutableCopy(由类NSString提供)复制了一个新的可变字符串作为方法信息的接收方。

 

10、数组:
有两个类提供了数组:NSArray和NSMutableArray。带有字符串的数组分为固定数组和可变数组两种。
[NSMutableArray array]
这个语句会产生一个空数组
NSMutableArray *myArray = [NSMutableArray array];
[myArray addObject:@"first string"];
[myArray addObject:@"second string"];
[myArray addObject:@"third string"];
int count = [myArray count];
NSLog(@"There are %d elements in my array", count);

置换数组内元素要使用到方法“replaceObjectAtIndex:… withObject:…”。
[myArray replaceObjectAtIndex:1 withObject:@"Hello"];

内存管理:
为了帮助你处理那些不在被使用的对象,Cocoa给每个对象关联了一个计数器,被称做“保留计数器”。
编程时,给对象增加一条援引信息,就要让对象在它的计数器里加一;当减少一次援引,则减一。
当保留计数器的计数为0的时候,对象就知道自己已经不再被援引了,可以被安全的毁掉了。
这时候的对象会毁掉自己并释放出内存空间。

 

11、开发常用网站资源:
苹果开发者主页:http://www.apple.com/developer
http://osx.hyperjeff.net/reference/CocoaArticles.php
http://www.cocoadev.com/
http://www.cocoabuilder.com/
http://www.stepwise.com/
上述网站还提供大量的链接指向其他更多的资源。你还应该订阅“cocoa-dev”邮件列表(网址
http://lists.apple.com/mailman/listinfo/cocoa-dev)。在这里你可以进行提问,热心的网友
们总会尽己所能帮助你解决问题。当然,你要注意礼貌,而且应当首先自己试着解决(参考
http://www.cocoabuilder.com/ )。http://www.catb.org/~esr/faqs/smart-questions.html
面上的“How To Ask Questions The Smart Way”则是告诉你如何恰当的提问。

还有一些优秀的关于Cocoa开发的书籍。Stephen Kochan编写的《Programming in Objective-C》
是为初学者准备的。其它一些书则要求你具备本书所将到的基础知识。我们比较推崇Aaron Hillegass
编写的《Cocoa Programming for Mac OS X》,他本人则是在Big Nerd Ranch教授这方面的课程。我
们同样向您推荐James Duncan Davidson和苹果公司合作编写的,由O'Reilly出版的《Cocoa withObjective-C》一书。

posted @ 2008-08-30 22:46 猫咪 阅读(1024) | 评论 (1)编辑

1 取得设备ID

#include

extern "C" __declspec(dllimport)

BOOL KernelIoControl(

DWORD dwIoControlCode, LPVOID lpInBuf, DWORD nInBufSize,

LPVOID lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned

);

#define IOCTL_HAL_GET_DEVICEID CTL_CODE(FILE_DEVICE_HAL, 21,

METHOD_BUFFERED, FILE_ANY_ACCESS)

CString GetSerialNumberFromKernelIoControl()

{

DWORD dwOutBytes;

const int nBuffSize = 4096;

byte arrOutBuff[nBuffSize];

BOOL bRes = ::KernelIoControl(IOCTL_HAL_GET_DEVICEID,

0, 0, arrOutBuff, nBuffSize, &dwOutBytes);

if (bRes) {

CString strDeviceInfo;

for (unsigned int i = 0; i
CString strNextChar;

strNextChar.Format(TEXT("%02X"), arrOutBuff);

strDeviceInfo += strNextChar;

}

CString strDeviceId =

strDeviceInfo.Mid(40,2) +

strDeviceInfo.Mid(45,9) +

strDeviceInfo.Mid(70,6);

return strDeviceId;

} else {

return _T("");

}

}

说明:Windows Mobile 5.0已经添加了专门的API完成此任务,对于2003以下的设备可以用

此方法。此方法是否能取道ID还取决与硬件制造商是否已经实现了改方法。因为

smartphone具备2-Tie安全性,所以此方法如果没有授权证书可能会调用失败。

2 取得设备信息

TCHAR wszMachineName[128];

SystemParametersInfo(SPI_GETOEMINFO, sizeof(wszMachineName),

&wszMachineName, 0);

取得设备OEM信息。

TCHAR wszVersion[256];

SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(wszVersion),

&wszVersion, 0);

取得平台信息。

3 创建GUID

CString CreateGUID()

{

TCHAR wGuid[37];

SYSTEMTIME systime;

FILETIME filetime;

// construct GUID

GetSystemTime(&systime);

SystemTimeToFileTime(&systime,&filetime);

DWORD tick=GetTickCount();

DWORD highWord=filetime.dwHighDateTime+0x146BF4;

// convert GUID to a string

wsprintf(wGuid,TEXT("%08.8x-%04.4x-%04.4x-%04.4x-%04.4x%04.4x%04.4x"),

filetime.dwLowDateTime,

LOWORD(highWord),

HIWORD(highWord |0x10000000),

LOWORD(rand()),

HIWORD(tick),

LOWORD(tick),

LOWORD(rand()));

return CString(wGuid);

}

posted @ 2008-08-27 10:03 猫咪 阅读(2) | 评论 (0)编辑
     摘要: 一、空指针问题 1、指针在使用前没有做为空判断,导致程序Crash 2、指针在new之后没有判断是否new成功 3、类成员指针没有初始化,却在析构函数中判断是否为空并删除 二、内存越界问题 内存越界导致的问题往往比空指针来得更严重,因为有很高的几率可能导致死机。 以下是我们采取的解决方案:   阅读全文
posted @ 2008-07-24 16:04 猫咪 阅读(51) | 评论 (0)编辑

 

在Windows Mobile开发中,显示图片时一般习惯使用voimage。但最近发现在调用voimage时是存在内存泄露的。

下面是voimage 的 Load函数的代码

 

BOOL CVOImage::Load(HDC hdc, LPCTSTR pcszFileName)
{
    
if(m_hbitmap)
    
{
        
if(GetFileName().GetLength() && GetFileName() == pcszFileName)
            
return TRUE;    // Already Loaded

        DeleteObject(m_hbitmap);
    }


    
if(!m_hdc)
    
{
        m_hdc 
= CreateCompatibleDC(hdc);

        HBITMAP    hbitmap 
= CreateCompatibleBitmap(hdc, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES));

        SelectObject(m_hdc, hbitmap);
    }


    BYTE    szBuffer[
1024= {0};
    HANDLE hFile 
= INVALID_HANDLE_VALUE;

#ifdef _WIN32_WCE
    HRESULT hr;

    DecompressImageInfo    dii;
#endif

    hFile 
= CreateFile(pcszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
    
if (hFile == INVALID_HANDLE_VALUE)
    
{
        DWORD dwError 
= GetLastError();
        
return FALSE;
    }


#ifdef _WIN32_WCE
    
// Fill in the 'DecompressImageInfo' structure
    dii.dwSize = sizeof( DecompressImageInfo );        // Size of this structure
    dii.pbBuffer = szBuffer;                        // Pointer to the buffer to use for data
    dii.dwBufferMax = 1024;                            // Size of the buffer
    dii.dwBufferCurrent = 0;                        // The amount of data which is current in the buffer
    dii.phBM = &m_hbitmap;                            // Pointer to the bitmap returned (can be NULL)
    dii.ppImageRender = NULL;                        // Pointer to an IImageRender object (can be NULL)
    dii.iBitDepth = GetDeviceCaps(hdc,BITSPIXEL);    // Bit depth of the output image
    dii.lParam = ( LPARAM ) hFile;                    // User parameter for callback functions
    dii.hdc = m_hdc;                                // HDC to use for retrieving palettes
    dii.iScale = g_iScale;                            // Scale factor (1 - 100)
    dii.iMaxWidth = g_iMaxWidth;                    // Maximum width of the output image
    dii.iMaxHeight = g_iMaxHeight;                    // Maxumum height of the output image
    dii.pfnGetData = GetImageData;                    // Callback function to get image data
    dii.pfnImageProgress = ImageProgress;            // Callback function to notify caller of progress decoding the image
    dii.crTransparentOverride = ( UINT ) -1;        // If this color is not (UINT)-1, it will override the
                                                    
// transparent color in the image with this color. (GIF ONLY)

    
// del for yulong
    
// Process and decompress the image data
//    hr = DecompressImageIndirect( &dii );
#endif
    
    
// Clean up 
    CloseHandle( hFile );

    HBITMAP hbitmapOld 
= (HBITMAP)SelectObject(m_hdc, m_hbitmap);

    DeleteObject(hbitmapOld);

    BITMAP    bmp;

    GetObject(m_hbitmap, 
sizeof(BITMAP), &bmp);

    m_dwWidth 
= bmp.bmWidth;
    m_dwHeight 
= bmp.bmHeight;

    m_strFileName 
= pcszFileName;
    m_dwResourceID 
= 0;
    m_hmoduleResource 
= 0;

    
return TRUE;
}

 

其中在CreateCompatibleBitmap时产生的内存位图的句柄被赋给了一个临时变量,使用完毕后却没有将其Delete,

我认为这里是有内存泄露了,导致每Load一次图片就是一次泄露

 

    if(!m_hdc)
    
{
        m_hdc 
= CreateCompatibleDC(hdc);

        HBITMAP    hbitmap 
= CreateCompatibleBitmap(hdc, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES));

        SelectObject(m_hdc, hbitmap);
    }

 


  

posted @ 2008-07-22 15:01 猫咪 阅读(26) | 评论 (2)编辑
正文:
我曾经参与过一个比较大的项目,在这个项目里面,我们没有一个完全确定的设计文档,所以程序的实现常常变动。虽然我们有一个比较灵活的框架,但是从程序的角度来讲,它使我们的程序非常的混乱。直到发布的日期临近,我们还没有一个稳定的可以用来做alpha测试的版本。所以我们必须尽快的删除掉无用的代码,让这个版本足够的稳定。但是,在这个没有足够规范的软件公司,我们没有时间也没有足够的精力来做边界测试之类的工作。所以我们只能采用变通的办法。在软件中最大的问题就是内存泄漏。因为往往出现这样的情况,我们在一段代码中分配了内存,但是却没有释放它。这造成了很大的问题。我们需要一个简单的解决方案,能够简单的编译进这个项目,在运行的时候,它能够产生一个没有被释放的内存的列表,用这个列表,我们能够改正程序的错误。这就是我们称之为内存跟踪的方法。首先,我们需要一种代码,能够被加入到源代码中去,而且这种代码能够被重用。代码重用是一种很重要的特性,能够节省大量的时间和金钱以及程序员的劳动。另外,我们的这种代码必须简单,因为我们当时已经没有那么多的时间和精力去完全重看一遍所有的代码来重新编写以及改正错误从而使内存跟踪能够起作用。

好在,我们总能够找到解决的办法。首先,我们检查了代码,发现所有的代码都是用new来分配内存,用delete来释放内存。那么,我们能够用一个全程替换,来替换掉所有的new和delete操作符吗?不能。因为代码的规模太大了,那样做除了浪费时间没有别的任何好处。好在我们的源代码是用C++来写成的,所以,这意味着没有必要替换掉所有的new和delete,而只用重载这两个操作符。对了,值用重载这两个操作符,我们就能在分配和释放内存之前做点什么。这是一个绝对的好消息。我们也知道该如何去做。因为,MFC也是这么做的。我们需要做的是:跟踪所有的内存分配和交互引用以及内存释放。我们的源代码使用Visual C++写成,当然这种解决方法也可以很轻松的使用在别的C++代码里面。要做的第一件事情是重载new和delete操作符,它们将会在所有的代码中被使用到。我们在stdafx.h中,加入:
#ifdef _DEBUG
inline void * __cdecl operator new(unsigned int size, 
const char *file, int line)
{
};

inline void __cdecl operator delete(void *p)
{
};
#endif
这样,我们就重载了new和delete操作符。我们用$ifdef和#endif来包住这两个重载操作符,这样,这两个操作符就不会在发布版本中出现。看一看这段代码,会发现,new操作符有三个参数,它们是,分配的内存大小,出现的文件名,和行号。这对于寻找内存泄漏是必需的和重要的。否则,就会需要很多时间去寻找它们出现的确切地方。加入了这段代码,我们的调用new()的代码仍然是指向只接受一个参数的new操作符,而不是这个接受三个参数的操作符。另外,我们也不想记录所有的new操作符的语句去包含__FILE__和__LINE__参数。我们需要做的是自动的让所有的接受一个参数的new操作符调用接受三个参数的new操作符。这一点可以用一点点小的技巧去做,例如下面的这一段宏定义,
#ifdef _DEBUG
#define DEBUG_NEW new(__FILE__, __LINE__)
#else
#define DEBUG_NEW new
#endif
#define new DEBUG_NEW
现在我们所有的接受一个参数的new操作符都成为了接受三个参数的new操作符号,__FILE__和__LINE__被预编译器自动的插入到其中了。然后,就是作实际的跟踪了。我们需要加入一些例程到我们的重载的函数中去,让它们能够完成分配内存和释放内存的工作。这样来做, #ifdef _DEBUG
inline void * __cdecl operator new(unsigned int size,
const char *file, int line)
{
void *ptr = (void *)malloc(size);
AddTrack((DWORD)ptr, size, file, line);
return(ptr);
};
inline void __cdecl operator delete(void *p)
{
RemoveTrack((DWORD)p);
free(p);
};
#endif
另外,还需要用相同的方法来重载new[]和delete[]操作符。这里就省略掉它们了。
最后,我们需要提供一套函数AddTrack()和RemoveTrack()。我用STL来维护存储内存分配记录的连接表。
这两个函数如下:
typedef struct {
DWORD address;
DWORD size;
char file[64];
DWORD line;
} ALLOC_INFO;

typedef list<ALLOC_INFO*> AllocList;

AllocList *allocList;

void AddTrack(DWORD addr, DWORD asize, const char *fname, DWORD lnum)
{
ALLOC_INFO *info;

if(!allocList) {
allocList = new(AllocList);
}

info = new(ALLOC_INFO);
info->address = addr;
strncpy(info->file, fname, 63);
info->line = lnum;
info->size = asize;
allocList->insert(allocList->begin(), info);
};

void RemoveTrack(DWORD addr)
{
AllocList::iterator i;

if(!allocList)
return;
for(i = allocList->begin(); i != allocList->end(); i++)
{
if((*i)->address == addr)
{
allocList->remove((*i));
break;
}
}
};
现在,在我们的程序退出之前,allocList存储了没有被释放的内存分配。为了看到它们是什么和在哪里被分配的,我们需要打印出allocList中的数据。我使用了Visual C++中的Output窗口来做这件事情。
void DumpUnfreed()
{
AllocList::iterator i;
DWORD totalSize = 0;
char buf[1024];

if(!allocList)
return;

for(i = allocList->begin(); i != allocList->end(); i++) {
sprintf(buf, "%-50s: LINE %d, ADDRESS %d %d unfreed ",
(*i)->file, (*i)->line, (*i)->address, (*i)->size);
OutputDebugString(buf);
totalSize += (*i)->size;
}
sprintf(buf, "----------------------------------------------------------- ");
OutputDebugString(buf);
sprintf(buf, "Total Unfreed: %d bytes ", totalSize);
OutputDebugString(buf);
};
现在我们就有了一个可以重用的代码,用来监测跟踪所有的内存泄漏了。这段代码可以用来加入到所有的项目中去。虽然它不会让你的程序看起来更好,但是起码它能够帮助你检查错误,让程序更加的稳定。
posted @ 2008-07-08 00:34 猫咪 阅读(5) | 评论 (0)编辑

偶半年前写的文章,在这边也发表一下

     先从Windows ce说起,有些朋友问我是做什么的,我说我做wince的,做技术的朋友一般也就不用再做解释了,但是面对不懂技术的朋友就不容易说清楚。我一般也就回答说:跟windows差不多...
     当然,它的确和windows非常类似,只是定位不同。Windows ce是微软开发的嵌入式操作系统,简称是EOS。该系统为抢占式多任务的实时操作系统,具有模块化可定制的特点。与windows相比Windows ce要小许多,有文章说,它也比windows更快更可靠,但是我个人以为,可以更快更可靠也是因为它相对较小的缘故,当然,作为实时操作系统,在一些应用上的可靠性是会很高的。现在有一个问题,就是:Windows ce有多大的用途?和向我提出疑问的朋友们一样,在进入这个领域之初我自己也有过疑惑。那时我知道它用于嵌入式,也知道可以可以涉及多个领域,但是在国内的日常生活中还是很少像windows或linux一样可以的的确确的感受到它的存在。那么Windows ce到底存在与我们生活中的哪些角落呢?发现得太少,其实有时候是我们不够留心。平时我们在公路上见到交警手中拿着的用触笔写写画画的东西,偶尔坐火车,在进站前有警察拿着同样的东西登记一些乘客的信息...   这些都是Windows ce系统的设备。Windows ce可以应用在网络(网关路由),工业控制(机器生产线控制),测量设备,信息化家电,医疗设备,GPS导航相关设备。 可以应用到公安,城市交通,铁路,税务,城管,电力,野外作业,军事... 最后,还有一项应用,是贴近普通人们生活最近,也是发展前景最广阔的应用。也是我要主要介绍的:Windows moblie

     Windows ce作为一个可定制的系统,为了应用于移动通讯领域(比如手机),微软在Windows ce的基础上开发定制了Windows moblie。到今天为止Windows moblie的最新版本是6.1,虽然微软已经发布了Windows moblie7的功能预览,但是目前国内还见不到它的任何应用,准确来说它还未完成,仍然在在开发中。

     Windows moblie的基础上又有2个不同的定制,分别是smartphone 和 Pocket PC。smartphone看名字就可以联想到了,它应用于移动电话,而Pocket PC起初是用于掌上电脑,默认情况下并不具备电话功能,但是经过后来的改变。现在我们一般见到的Pocket PC的版本都是和smartphone一样,应用于手机。这两个同属于Windows moblie的子版本,最主要的区别也就是触笔的支持上。只有Pocket PC是支持触笔的。在它们上面的应用程序开发,在考虑周全的情况下,是可以相互移植的,本质区别并不多。要提醒一点,要在smartphone 和 Pocket PC轻松的相互移植要注意的是,最好不要使用MFC,因为微软为了给smartphone瘦身,并不提供对MFC的支持。 如果你急于动手,盲目的先实现了一个使用MFC的Pocket PC的应用,在实现smartphone上的移植时,你的程序很大块的面积将必须要重写。一般情况下,先从smartphone入手,再向Pocket PC移植是比较正确的选择,因为相对于Pocket PC,smartphone的某些支持更少,应该这样想,就像在同一个系统下,功能更多的高版本和低版本,做到向下兼容绝对比向上兼容要容易得多。

做Windows moblie开发,首先要接触的是它的开发工具。较早被使用的是EVC,一种开发界面和使用习惯类似于VC的开发工具,同样是使用C++作为开发语言。他最新的版本是EVC4 sp4,但是因为微软已经放弃对它的持续更新,以后也不会有新的版本出现了,现在已经不是我们做Windows moblie开发的首选工具了。而另一款同样被微软放弃的工具EVB,因为基于VB的更弱小的功能,则几乎已经被人们遗忘了。现在,在VS2008还没有被大肆推广前,VS2005应该说是Windows moblie开发的首选工具。

       目前Windows Mobile的开发语言有.NET(包括C#和VB.NET)和C++。C#近几年一直深受微软的大力推广,虽然很多老牌的程序员并不看好它,但事实上它的推广还是做得很好的。目前我个人估计,国内在Windows moblie的应用程序开发上C#程序员的数量是多过C++的。当然,得出这个结论是有理由的。网上一些关于Windows moblie的论坛,讨论群等,都是基于.net开发的数量较多,而.net又尤以C#为主打。如果要搜寻Windows moblie开发的C++中文资料,一般来讲是相对比较少的。目前为止我也没有见到过中文的以C++为基础介绍Windows moblie开发的书籍,准确来说也并不是一本都没有,只是没有真正有用的可以作为教材的。想反,以C#为基础介绍Windows moblie的中文书籍近来还是出了一些。可见C#的市场貌似是要大些的。在一些政府部门和一些小的开发公司,做Windows moblie的开发现在已经基本都是使用C#。说了C#这些好处,并不代表我是C#的支持者。归到低,它只是一个开发的语言工具,市场大的根本原因,是它的简单易用。谁不喜欢简单的东西,C++实在是有过复杂。一些网上使用C#的开发同行在知道我一直使用C++后,认为我有自虐倾向。当然,这是他们在开玩笑。不过话说回来,由简入奢易,由奢入简难,所有我还是认为,做开发,从c\c++开始起步是明智的选择。不管有多少初学者在研究C#,现在大的开发公司,比如多普达,腾讯等等,都仍然是使用c\c++为主的,C#的功能和性能毕竟是有局限的。

       最后,介绍一下我所熟悉的开发方式。Windows Mobile5.0以前的版本做开发,除了EVC还有vs2003可以选择,如果项目是现在才开始的,这些工具其实都可以抛弃了,与vs2005相比,它们显得很不好用。vs2005做Windows Mobile开发仍然是微软一贯的做法,它是向下兼容的,同时可以开发5.0和之前的版本。需要的准备工作就是从微软的网站上下载相应版本的SDK。目前已经有6.0的sdk可以下载。上一篇我提到了在Windows Mobile下的两个主要版本smartphone和Pocket PC之间做到软件可移植的问题。这里再详述一下。在使用C++的情况下,为了移植的方便,一般不要在开发Pocket PC的时候使用MFC。但是,不用MFC,用什么?直接使用Windows Mobile的SDK也是一种选择,但是这样的开发还是做起来比较繁琐的。现在,WTL在Windows开发上人们已经使用得很多了。它有很多优点,比如开发出的程序要比MFC的东西小不少,而且方便好用,它的准确介绍可以google一下其相关说明,我在这里就不多说。因为Windows Mobile的SDK和windows开发的win32 sdk的一致性,WTL对Windows Mobile的SDK也是完全支持的。要在vs2005下使用WTL,其版本至少在7以上,个人推荐WTL8.0。就像MFC一样,在安装以后,它同样可以在vs下生成Windows Mobile开发的向导选项。有了这些工具,我们就可以做Windows Mobile的开发了。但是目前国内在Windows Mobile开发领域的学习资料数量还是很有限的。要充分发掘Windows Mobile开发的潜力,就必须有快速熟悉它的方式。这一点微软做得很贴心,除了相应SDK自带的帮助文档外还有内容丰富的MSDN,如果这些还不够直观,微软还在相应SDK安装目录下的sample目录下放了很多的实例程序,对Windows Mobile开发需要的常用功能一一做了例子。

posted @ 2008-07-07 19:18 猫咪 阅读(53) | 评论 (1)编辑
上一周的雨来得厉害,把我淋了个遍。近些天来,雨气是依然未绝。

这两周看到关于TD,发放3G的牌照的文章不少。甚感心酸,中国3G的到来已经太晚,还要被种种利益集团
来回牵绊,如此以往,中国的无线网络,不要说赶上世界先进水平,连世界的平均中下水平能否保住都是问题。
posted @ 2008-06-12 19:25 猫咪 阅读(29) | 评论 (0)编辑
博客开张,可喜可贺
posted @ 2008-05-23 09:29 猫咪 阅读(12) | 评论 (0)编辑