C C 程式設計規範

2021-07-11 05:52:29 字數 4425 閱讀 6201

1、注意:strncpy、strncat等帶n版本的字串操作函式在源字串長度超出n標識的長度時,會將包括』\0』結束符在內的超長字串截斷,導致』\0』結束符丟失。這時需要手動為目標字串設定』\0』結束符。

char dst[11];     // 【注意】最好每次定義時初始化為0: dst[11] = ;

char src = "0123456789";

char *tmp = null;

memset(dst, '@', sizeof(dst));

memcpy(dst, src, strlen(src));

dst[sizeof(dst) - 1] = 』\0』; //【修改】dst以』\0』結尾

在使用像memcpy、strcpy、strncpy、sscanf()、sprintf()、snprintf()和wcstombs()這樣的函式時,複製重疊物件會存在未定義的行為,這種行為可能破壞資料的完整性。

memcpy與memmove的目的都是將n個位元組的源記憶體位址的內容拷貝到目標記憶體位址中。

但當源記憶體和目標記憶體存在重疊時,memcpy會出現錯誤,而memmove能正確地實施拷貝,但這也增加了一點點開銷。

memmove的處理措施:

當源記憶體的首位址等於目標記憶體的首位址時,不進行任何拷貝

當源記憶體的首位址大於目標記憶體的首位址時,實行正向拷貝

當源記憶體的首位址小於目標記憶體的首位址時,實行反向拷貝

#define buf_size 128

void compliant()

//通過精度限制從argv[0] 中只能拷貝 100 個位元組。

無符號數u1 u2,在計算u1+u2時,需要判斷u1+u2是否大於uint_max

if((uint_max - ui1) < ui2) //【修改】確保無符號整數運算時不會出現反轉

else

int32 si1, int32 si2;

int64 tmp = (int64)si1 *(int64)si2; /*【修改】確保有符號整數運算時不會出現溢位 */

//++ 將32位有符號數轉換成64位,並且計算完成後需要比較結果是否有符號數的範圍內

if((int_max < tmp) || (int_min > tmp))

【截斷錯誤】將乙個較大整型轉換為較小整型,並且該數的原值超出較小型別的表示範圍,就會發生截斷錯誤,原值的低位被保留而高位被丟棄。

【符號錯誤】從帶符號整型轉換到無符號整型會發生符號錯誤,符號錯誤並不丟失資料,但資料失去了原來的含義。帶符號整型轉換到無符號整型,最高位(high-order bit)會喪失其作為符號位的功能。如果該帶符號整數的值非負,那麼轉換後值不變;如果該帶符號整數的值為負,那麼轉換後的結果通常是乙個非常大的正數。

//++[符號錯誤繞過長度檢查]

int length; //++ 宣告為無符號數

char buf[buf_size];

length = atoi(argv[1]); //【錯誤】atoi返回值可能為負數

if (length

< buf_size) // len為負數,長度檢查無效

uint32 blocknum;

uint64 alloc = (uint64)blocknum * 16; /*【修改】確保整型表示式轉換時不出現數值錯誤 */

//++ 先將兩個32位的數之積轉換為64位再賦值給64位的變數。

說明:位操作符(~、>>、<

申請記憶體後初始化(memset )

禁止記憶體指標移動後(非malloc分配後的起始值),通過該指標釋放記憶體,會出現未知錯誤。因為malloc一塊記憶體後,它的前乙個位元組存放了分配的記憶體大小,free時會根據該位元組所代表的大小去free記憶體。

禁止使用system()和popen()。替代方案是posix的exec系列函式或win32 api createprocess()等與命令直譯器無關的程序建立函式來替代。

錯誤示例:

system(sprintf("any_exe %s", input)); //【錯誤】引數不是硬編碼,禁止使用system
if (execve("/usr/bin/any_exe", args, envs) == -1) /*【修改】使用execve代替system */
說明: std::ostrstream的使用上需要特別注意幾點:

(1)str() 會呼叫成員函式freeze(),它會凍結字串行,當緩衝區不夠大以至於需要分配新緩衝區時,這麼做可以避免事情變得複雜。

(2)str()不會附加字串終止符號(』\0』)。

(3)data()返回所有字串,沒有附帶』\0』結尾字元(目前有些編譯器自動呼叫c_str方法了)。

上面如果不注意,就可能會導致記憶體訪問越界、緩衝區溢位等問題,所以建議不要使用ostrstream。[c++03]標準將std::strstream標明為deprecated,替代方案是std::stringstream。ostringstream沒有上述問題。

錯誤示例:下列**使用了std::ostrstream,可能會導致記憶體訪問越界等問題。

void nocompliant()

c標準的系列字串處理函式strcpy/strcat/sprintf/scanf/gets,不檢查目標緩衝區的大小,容易引入緩衝區溢位的安全漏洞。

c++標準庫提供了字串類抽象的乙個公共實現std::string,支援字串的常規操作

說明:字元輸入/輸出函式fgetc()、getc()和getchar()都從乙個流讀取乙個字元,並把它以int值的形式返回。如果這個流到達了檔案尾或者發生讀取錯誤,函式返回eof。fputc()、putc()、putchar()和ungetc()也返回乙個字元或eof。

如果這些i/o函式的返回值需要與eof進行比較,不要將返回值轉換為char型別

因為char是有符號8位的值,int是32位的值。如果getchar()返回的字元的ascii值為0xff,轉換為char型別後將被解釋為eof。0xff這個值被有符號擴充套件後是0xffffffff,剛好等於eof的值。

注意:對於sizeof(int) == sizeof(char)的平台,用int接收返回值也可能無法與eof區分,這時要用feof()和ferror()檢測檔案尾和檔案錯誤。

void  compliant(char *lpinputpath)

windows下可以使用pathcanonicalize函式對檔案路徑進行標準化:

void  compliant(char *lpinputpath)

說明:該建議應用場景如下,當對檔案的元資訊進行操作時(比如修改它的所有者、對檔案進行統計,或者修改它的許可權位),首先要開啟該檔案,然後對開啟的檔案進行操作。只要有可能,應盡量避免使用獲取檔名的操作,而是使用獲取檔案描述符的操作。這樣做將避免檔案在程式執行時被替換(一種可能的競爭條件)。

例如,當access()和open()兩者都利用乙個字串引數而不是乙個檔案控制代碼來進行相關操作時,攻擊者就可以通過在access()和open()之間的間隙替換掉原來的檔案,如下所示:

錯誤示例:下列**使用access()函式,可能引發競爭條件問題。

void  noncompliant(char * file)

else

}

說明:呼叫容器的erase(iter)方法後,迭代子指向的物件被析構,迭代子已經失效,如果再對迭代子執行遞增遞減或者引用操作會導致程式崩潰。

//++ 錯誤用法:

m_mapid2ne.erase(iter);

iter++; //【錯誤】erase後,iter指向的物件可能已失效

//++ 正確用法:

m_mapid2ne.erase(iter++); //【修改】將迭代子後置遞增作為erase引數

也可以使用earse方法的返回值來儲存迭代子,因為返回的是被刪除元素迭代子指向的下乙個元素位置:iter = erase(iter)

注意這種用法可以用於list和vector的erase(),但不適用於map。因為std::map::erase()的返回值在不同stl實現版本是有差異的,有的有返回值,有的沒有返回值,所以對map只能使用推薦做法。

c c 的程式設計規範

乙個程式設計師的編碼水平如何,從他寫的 的風格,布局就可以看出來。所以良好的編碼風格是非常重要的。清晰易讀的 才是高質量的 下面是我從網上找到的乙個關於編碼風格的帖子。對於程式設計的初學者比較有用,高手就不必瀏覽了。一 每日編寫如此之多的 很多同學現在的想法是,我要實現功能,實現了功能以後,萬事大吉...

C C 對比學習 google C 程式設計規範

c和c 的關係 學習任何一門新的語言都必須對已學過的進行思考,找出異同點,方便學習新語言的特性。c 的意思 c plus plus c 是完全相容c語言的,其中很多特性都能體現出來。c c stdio.h printf scanf 函式無過載,且結構體不能為空 過程 c cpp iostream 引...

17 C C 程式設計規範精述

c c 程式設計規範精述 匈牙利命名法 1 排版上不同小結構間要空行分開,子邏輯項相對父邏輯項要縮排 及if,while 等判斷語句應獨佔行並對齊,且後加空格以顯突出。2 注釋位於相應 上面或右旁邊。且與其它 空行或空格隔開。3 變數命名風格 採用 unix 的全小寫加下劃線的風格或大小寫混排的方式...