本文討論一些常見的MySQLC API 程序設計錯誤,以及如何避免其發生這些問題在MySQL郵件清單中會周期性地突然出現)。
1. 錯誤1——使用未初始化的連接處理程序指針
我們已經通過傳遞NULL 參數調用了mysql_ i n i t ( ),這就是讓它分配並且初始化MYSQL 結構,然後返回一個指針。另外一種方法是將指針傳遞到一個已有的MYSQL 結構中。在這種情況下, mysql_init() 會將結構初始化並返回一個指針,而不必自己分配結構。如果要使用第二種方法,則要小心會出現一些微妙的問題。下面的討論指出了需要注意的一些問題。如果將一個指針傳遞給mysql_ init( ),它應該實際指向某些東西。看下面的代碼段:
這個問題是,mysql_init() 得到了一個指針,但指針沒有指向所知的任何地方。conn 是一個局部變量,因此在main() 開始執行時它是一個能指向任何地方的未初始化的存儲器,這就是說mysql_init() 將使用指針,並可在內存的一些任意區域濫寫。如果幸運的話, conn 將指向您的程序地址空間的外部,這樣,系統將立即終止,使您能盡早意識到代碼中出現的問題。
如果不幸的話, conn 將指向程序中以後才使用的一些數據的內部,直到再次使用那個數據時才發現問題。因此實際出現問題的地方遠比執行程序時出現的問題多,也更難捕捉到。下面是一段有問題的代碼:
此時, conn 是一個全局變量,因此在程序啟動前,將它初始化為0就是NULL)。mysql_init() 遇到NULL 參數,因此初始化並分配一個新的連接處理程序。只要將conn 傳遞給需要非NULL 連接處理程序的MySQLCAPI 函數,系統就會崩潰。這些代碼段的修改就是確保conn 有一個可知的值。例如,可以將它初始化到已經分配的MYSQL 結構地址中去:
然而,推薦的較容易的!)解決方案僅僅是將NULL 顯式地傳遞給mysql_ init( ),讓該函數分配MYSQL 結構,並將返回值賦值給conn:
無論如何不要忘記檢驗mysql_init() 的返回值,以確保它不是NULL。
2. 錯誤2——有效結果集檢驗的失敗
請記住檢查希望得到的結果集的調用狀態。下面的代碼沒有做到這一點:
不幸地是,如果mysql_store_result() 失敗,res_set 為NULL,while 循環也不執行了,應測試返回結果集函數的返回值,以確保實際上在進行工作。
3. 錯誤3—— NULL 列值引起的失敗
不要忘記檢查mysql_fetch_row() 返回的數組MYSQL_ROW 中列值是否為NULL 指針。如果row[i] 為NULL,則在一些機器上,下面的代碼就會引起崩潰:
該錯誤危害最大的部分是,有些printf() 的版本很寬容地對NULL指針輸出了“( null )”,這就使錯誤很容易逃脫而沒有把錯誤定位。如果把程序給了朋友,而他只有不太寬容printf( )版本,程序就會崩潰,您的朋友會認為您是個無用的程序員。循環應該寫成下面這樣:
不需要檢查列值是否為NULL 的惟一一次是當已經從列信息結構確定IS _ NOT _ NULL( )為真時。
4. 錯誤4——傳遞無意義的結果緩沖區
需要您提供緩沖區的客戶機庫函數通常要使這些緩沖區真正存在,下面的代碼違反了這個規則:
問題是什麼呢?to_str 必須指向一個存在的緩沖區,而在這個樣例中沒有,因此,它指向了隨意的位置。不要向mysql_escape_string 傳遞無意義的指針作為to_str 參數,否則它會恣意踐踏內存。