我被要求維護一個充滿內存泄漏的大型C++代碼庫。當我發現,我發現我們有很多導致泄漏的緩衝區溢出(這是怎麼回事,我從不想知道)。什麼C/C++函數最常被錯誤地使用,並可能導致緩衝區溢出?
我決定首先刪除緩衝區溢出,從危險函數開始。哪些C/C++函數最常使用不正確,並可能導致緩衝區溢出?
對於用於幫助尋找緩衝區溢出,我已經created another question that deals with this
我被要求維護一個充滿內存泄漏的大型C++代碼庫。當我發現,我發現我們有很多導致泄漏的緩衝區溢出(這是怎麼回事,我從不想知道)。什麼C/C++函數最常被錯誤地使用,並可能導致緩衝區溢出?
我決定首先刪除緩衝區溢出,從危險函數開始。哪些C/C++函數最常使用不正確,並可能導致緩衝區溢出?
對於用於幫助尋找緩衝區溢出,我已經created another question that deals with this
這裏編譯器和/或工具的一些功能,我發現是危險的:)
下面的鏈接應該給你用C安全功能++(那些是固定後用「_s」解決像溢出問題)綜合來看:http://msdn.microsoft.com/en-us/library/8ef0s5kh(VS.80).aspx
編輯:此鏈接包含已被替換的具體功能:http://msdn.microsoft.com/en-us/library/wd3wzwts(VS.80).aspx
編輯:我應該提到這是微軟的方法,但是鏈接仍然是識別被認爲紅旗功能非常有用。
不幸的是任何陣列可導致緩衝區溢出:
uint32_t foo[3];
foo[3] = WALKED_OFF_END_OF_ARRAY;
在功能方面,sprintf的將愉快地走下緩衝器的末端。它可以被snprintf取代。
通常,任何不檢查參數範圍的函數。名單將
您應該使用尺寸限制的版本一樣stncpy,strncat函數,與fgets,等等。然後在給出尺寸限制時要小心;考慮終止字符串的'\ 0'。
此外,數組不是在C或C++中檢查。以下示例會導致錯誤。見off by one error
int foo[3];
foo[3] = WALKED_OFF_END_OF_ARRAY;
編輯:@MrValdez的複製答案,@Denton金特里
基本上,任何事情接受一個指針和寫它,沒有檢查長度。所以像strcpy(),sprintf()等東西。
Memcpy()是另一個危險的。
訪問數組的任何循環都是一個危險點,因爲沒有停止超出數組的末尾。
內存泄漏是由分配內存引起的,沒有釋放內存。構造函數和析構函數應該是另一個強大的審查點,後者確保任何分配的內存都是空閒的。
您使用的是哪個版本的visual studio?在2008年啓用所有警告後,您提到的所有功能(以及更多)都會警告您已棄用它們。
也許你可以檢查所有的警告是否已打開,並讓編譯器爲你做好工作?
作爲一個便箋,優秀的writing secure code做了很好的工作,解釋了一些舊功能的不同之處。
我在工作的代碼庫上遇到了相同的問題。我的建議是:小心任何看起來像str *()和mem *()的C函數。也要小心任何需要指針指向緩衝區的東西,而且不會有長度。由於看起來你有機會使用C++,所以我會在最極端的情況下嘗試使用C++容器來處理事物:矢量,字符串,映射等等。這些讓你的生活變得更容易。
此外,自動化問題檢測工具也非常棒。如果你可以使用valgrind,我會推薦它。 Rational Purify也是非常強大的,雖然不便宜。
問題是從錯誤的結局開始,恐怕。假設緩衝區溢出發生在其他功能中。根據我的經驗,最常見的原因是operator ++,或者缺少操作符!=。
在Visual Studio 2005/8中找到一批的最佳解決方案是/ GS。它不會找到所有這些,但它是減少所需手動工作量的便宜方法。
Valgrind是你最好的朋友。
的valgrind --tool = MEMCHECK --leak校驗=全./a.out
在下另外疑難雜症是 「函數strncpy()」 函數。許多人沒有意識到它可以自由地返回一個非null結尾的字符串。
我不明白這個問題。如果小心處理,這裏沒有任何功能會導致溢出。 – unexist 2008-10-03 14:43:43
@unexist:如果使用正確,沒有任何功能會出錯。問題是哪些函數經常被錯誤地使用,並導致可能導致緩衝區溢出。 – 2008-10-03 14:50:58
你在使用什麼編譯器/平臺?有很多工具可以自動找到這類東西。 – twk 2008-10-03 15:49:14