開發隨筆

一,最近在調試一個程序,發現一個死循環,不過怎麼也看不出會死循環,代碼如下:
        DWORD dwData;
        LPTSTR buffer = NULL;
        DWORD buffersize = 0;
        while (!SetupDiGetDeviceRegistryProperty ( hDevInfo, DeviceInfoData,  Property,  &dwData,                                                                                                                 (PBYTE)buffer, buffersize, &buffersize)
                   )
        {
            if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
            {
                    // Change the buffer size.
                    if (NULL != buffer)
                        ::LocalFree(buffer)
                    buffer = (LPTSTR)(::LocalAlloc(LPTR,buffersize));
            }
            else
                return E_FAIL;
        }
     這段代碼從註冊表中獲取設備的相關屬性,關鍵是SetupDiGetDeviceRegistryProperty 函數的最後一個參數並未     如它的文檔所言(返回以“字節”爲單位的尺寸),而是返回以“字符”爲單位,當相關屬性值爲中文時,這段代碼        會陷入死循環,後來我將buffersize加大了一倍,就可以了。

二,搭建基於phpeclipse開發環境時犯的錯誤:
    主要是參考這篇文章:Eclipse在PHP開發中的使用
    1,單擊工具欄上的停啓apache和mysql失敗。
            解決方法:要先將apache和mysql註冊成服務。
    2,PHP Browser不能正常工作,原來是配置apache出錯,別名是用Alias而不是ScriptAlias(都是copy惹的禍)。
    3,最開始ctrl+空格可調出智能提示窗口,後來突然不管用了,原來要使用alt+/。

三,Linux下的用戶權限問題:
 最近搭建了一個cvs服務器,在倉庫的用戶權限上吃足了苦頭,使用的訪問協議是ssh,希望只有cvs用戶組成員和root用戶才能訪問倉庫目錄(其他用戶無任何權限),倉庫是初始化了,目錄樹的所屬權和訪問權限都設置好了,把我的個人用戶帳號加入到cvs組中後,用wincvs登錄成功,試了個項目動作正常,本以爲萬事大吉,但當加入第二個用戶後,用wincvs訪問倉庫總是出現權限錯誤。原來,當我提交修改後,修改了的文件的所屬權會變成我當前用戶及我的缺省分組,問題就出在這個缺省分組上,我用adduser命令時一向不指定-g選項的,結果
用戶的缺省分組名與用戶名相同,這樣改過文件別人都無法訪問了,後來用usermod命令將所有cvs用戶的缺省分組改成cvs後,就好了。

四,boost.regex中匹配中文正則表達式的一個錯誤:
     網上搜到了表達式:[/u4e00-/u9fa5],在vc2005下調了ok,但在其它編譯器上調試後發現/u並非合法的轉義用字符,估計表達式是用在其它語言裏的,正確的應該是/x,表達式應該爲:[/x4e00-/x9fa5]。

五,用ajax和setTimeout函數寫一個動態刷新網頁部分內容的javascript時,在Firefox下運行正常,但在IE下運行出現出錯提示:對象不支持此屬性或方法。
進入Microsoft Script Debugger後顯示的詳細錯誤信息如下:
A debugger break at "JScript - anonymous function" could not be handled because the source document could not be found.
出錯的代碼行:notify = document.getElementById("notify");
上面這一行代碼是在XMLHttpRequest的回調函數中執行的,前一行代碼更改了notify頁面元素的內容。
經試驗,發現將notify = document.getElementById("notify");放到回調函數之外,回調函數只使用notify變量就OK了。

六,在limodou的blog上看到的一則技巧:
執行一個reg文件,內容爲:

    Windows Registry Editor Version 5.00

    [HKEY_CLASSES_ROOT/Directory/shell/cmd/command]
    @="cmd.exe /k /"cd %L/""

它的作用是在你的資源管理器上的右鍵菜單上增加一個菜單,名字爲cmd。
那麼以後你在目錄欄中點擊一個目錄,然後點右鍵,再執行這個cmd菜單,就會直接進入這個目錄的命令行。

七,頁面完成後IE進度條仍在慢慢前進:
當執行某個腳本後會轉到當前頁面時該問題纔會出現。利用排除法發現問題出在一個工具欄實現上,該工具欄上的按鈕是用鏈接實現的,該鏈接的樣式中用了背景圖,鼠標放上去後(hover樣式)用不同的背景圖,該鏈接的代碼如下:
<div class="toolbar">
  <ul>
    <li><a title="刪除選中的所有記錄" href="#" _fcksavedurl=""#"" _fcksavedurl=""#"" _fcksavedurl=""#"" _fcksavedurl=""#"" _fcksavedurl=""#"" onClick="execOperate('delete',); return false;">刪除</a></li>
  </ul>
</div>
按此按鈕後,會轉到一個頁面執行刪除操作,從該頁面執行完後會跳轉到本頁面。
似乎是因爲IE在跳回本頁面後對鏈接的背景圖片的裝入方面有點秀逗,因爲鼠標放到鏈接上,IE進度條立刻正常了,鏈接不使用背景圖也沒這個問題,鏈接只使用 href或只使用onClick也沒這個問題,不過href是少不了的,否則鏈接就生動不起來了,最後通過把鏈接改爲:
        <a title="刪除選中的所有記錄" href="javascript:execOperate('delete',); ">刪除</a>
問題似乎解決了,只是IE的這個迷團仍在。
當一個按鈕是隱藏的且按鈕的樣式中有背景圖時,也會出現該問題(隔一次出現一次),通過去除樣式中的背景圖可解決該問題。

八,信息號量使用不當導致死鎖:
需要注意的是,信號量不像互斥體,一個線程兩次佔用信號量(第二次佔用時,前一次佔用並未釋放)將導致線程最終佔有了兩個信號量。在程序中,共信號量的最大數是5個,代表了對數據庫的5個連接,有多個線程(>5)要訪問數據庫,由於有的線程連續調用獲取連接的接口(未釋放先前獲得的連接,會佔用信號量),這樣當有5個線程分別獲取了一個連接,而爲了完成工作又需要再獲得一個連接(佔用信號量),就會出現死鎖。解決方法是調用代碼注意儘早釋放信號量,避免連續佔用信號量,一個更好的辦法或許是封裝信號量的訪問,讓一個線程最多隻能佔用一個信號量。

九,vc6帶的stl庫的string類因爲使用了引用計數導致在多線程應用中崩潰。
這是個老問題了,網上搜一下就一大把。
http://support.microsoft.com/kb/813810/zh-en
可以考慮使用stlport代替vc6的stl庫,關閉vc6的stl庫string中的引用計數,升級到更高版本的vc。

十,使程序在出現嚴重錯誤或異常時不彈出系統錯誤對話框
SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX);
參考:http://topic.csdn.net/t/20040913/23/3369198.html

十一,調用TerminateThread終止一個線程後,再調用GetExitCodeThread獲取到的線程退出代碼爲什麼不是TerminateThread中傳入的值,而是STILL_ACTIVE?
因爲TerminateThread函數是異步運行的函數。如果要確切地知道該線程已經終止運行,必須調用WaitForSingleObject或者類似的函數。

十二,bcc55中說找不到某個psdk中的庫?
使用時我發現,代碼或工程中不用指定psdk中的庫,bcc55就工作正常了,但切換到其他編譯器時又必需指定,
其實改變bcc55的配置就OK了,如下:
在bcc32.cfg中加入PSDK的路徑:
-I"D:/Program Files/Borland/BCC55/include"
-L"D:/Program Files/Borland/BCC55/lib;D:/Program Files/Borland/BCC55/lib/PSDK"
在ilink32.cfg中加入PSDK的路徑:
-L"D:/Program Files/Borland/BCC55/lib;D:/Program Files/Borland/BCC55/lib/PSDK"

十三,通過在源代碼中設置將庫鏈入工程
一直都是鏈入靜態庫,原來也可以鏈入動態庫:
#pragma comment(lib,"psapi.lib")   //鏈入靜態庫
#pragma comment (linker,"defaultlib:psapi.dll") //鏈入動態庫

十四,用ddk build驅動程序時現錯誤:error C2220: warning treated as error
原因在以下網頁中有討論:http://www.osronline.com/ShowThread.cfm?link=92376
不過解新決方案沒有挑明,其實只要在MAKEFILE的語句!INCLUDE $(NTMAKEENV)/makefile.def之前放置以下語句就OK了:
BUILD_ALLOW_ALL_WARNINGS=1

十五,軟件發行與升級
1,什麼時候該以綠色軟件方式發行?什麼時候因該製作安裝包?
當你發行的文件的數量大於1個的時候,或許你就該考慮做個安裝包了(除非是這多個文件其實是可以單獨運行或使用)。因爲當你通過爲用戶提供壓縮包進行升級時,會遇到意想不到的情況(比如:用戶解壓文件時不知道要解壓到什麼位置,用戶會想解壓到安裝目錄會不會把原有文件裏的數據文件覆蓋了?甚至用戶可能把你的綠色軟件目錄拷貝了很多份,然後他會不知道要把下下來的文件替換哪個目錄裏的文件?)。
2,用戶主動通過IE下載升級包還是程序中集成在線升級的功能?
我覺得應該是在程序中集成在線升級功能,首先這樣對用戶很方便,其次可以避免用戶在下載過程中遇到很多問題(比如:他裝了flashget,他未必會精於此道,特別是你使用固定的下載地址時,flashget之類的東西會說:該網址存在於正在下載表列中。鬼才知道還會遇到什麼下載工具)。

十六,mysqldump輸出的中文亂碼
導出結果直接在控制檯上輸出可能是因爲控制檯使用的默認字符集不是中文的(先執行chcp 936改爲中文),如果此時輸出還是亂碼,試試在導出命令中指定--default-character-set=<字符集>項,這個字符集應該是你創建數據庫時指定的,我的是--default-character-set=latin1。
參考:http://smiling.iblog.com/post/10/320118

十七,emacs編輯c源文件時,顯示的中文都是/0000之類的東西。
因爲源代碼裏有繁體字,ntemacs默認設置了按GB2312顯示,無法顯示繁體字,結果也不按GB2312進行顯示了。在源代碼的第一行加上: //-*- coding: gbk -*-
現在行了。
參考:http://bbs.chinaunix.net/viewthread.php?action=printable&tid=546293

十八,遭遇宏定義衝突
書上常說,慎用宏,因爲宏定義容易引起衝突,調試起來非常麻煩,這不終於讓我遇到了:
系統頭文件arpa/telnet.h中定義了#define IP  244     /* interrupt process--permanently */,然後項目的頭文件裏定義了int IP,結果編譯出錯(unnamed fields of type other than struct or union are not allowed
),動用GOOGLE甚至找出了是GCC3.1 的一個BUG,還好我用的是GCC3.2,否則估計現在本人正在升級GCC。現在只是在int IP之前來一句#undef IP,於是整個世界都清靜了。

十九,用tar製作安裝包的陷井
原來是用/bin/tar -rf app.tar /etc/init.d/app這種方式將一些啓動腳本打包的,後來我覺得這樣的話腳本不利於版本控制,於是建了個打包目錄,裏面的目錄結構和要安裝到的目標目錄一樣(裏面也有etc/init.d目錄用於放置腳本),這樣所有東西都可以放到SVN中,而且調試安裝包也一目錄瞭然,製作安裝包就很直觀了:
將打包目錄用svn export導到臨時目錄,將編譯出的程序拷貝到臨時目錄的相應位置,用tar -zcvf 將臨時目錄打包成安裝包。拿安裝包到虛擬機中一測運行OK,但重啓虛擬機後發現虛擬機的文件系統被損壞了,原因是linux中/etc/init.d是一個鏈接,而製作的安裝包中是一個真正的目錄,問題查出來了,更正就好辦了,安裝包中的目錄改成/etc/init.d鏈接到的真正目錄就行了。

二十,mysql命令行下導入.sql文件的兩種方式
       1,mysql -uroot  <  file.sql
       2,mysql  -uroot  -e "source  d:/file.sql"

二十一,用snprintf累加字符串的不可移植性
這項工作通常是用strncat完成,不過用strncat的話還是要隨時跟蹤dest緩衝區的當前長度,或臨時使用strlen求得,於是同事介紹了他常用的手法snprintf(dest, dest_buf_len, "%s%s", dest,  src),我一開始擔心性能問題,不過他解釋說看彙編知道會進行優化,不用擔心。後來實際使用時發現,這是不可移植的,只是在vc上可以,在gcc和bcc55上測試時發現上面的snprintf(dest, dest_buf_len, "%s%s", dest,  src)===strncpy(dest,  src, dest_buf_len),這導致dest的原始值部分丟失。

二十二,./configure 腳本不斷循環執行
是因爲系統的時間設置不對,比源代碼文件中的創建日期還要早,解決辦法就是將系統日期改爲當前日期。

二十三,windows下用sc命令創建服務總不成功
注意sc create  後的參數形式,sc create  binPath= c:/xxx.exe .......
其中,binPath=後是要接一個空格的,其它參數也類似。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章