table of contents
1.strcpy()函式
2.main()的返回型別
3.記憶體洩露
4.free()函式
5.使用_exit退出
6.void*和c結構體
7.*和++操作
8.問:修改**片段(或者唯讀**)
9.返回本地變數的位址
10.處理printf()的引數
問:下面是乙個簡單的密碼保護功能,你能在不知道密碼的情況下將其破解嗎?
#includeint main(int argc, char *ar**)
if(flag)
printf("\n password cracked \n");
else
printf("\n incorrect passwd \n");
return 0;
}
答:這道題前面專門有一篇推送寫過,有的人可能沒看,今天再講一遍。破解上述加密的關鍵在於利用攻破strcpy()函式的漏洞。所以使用者在向「passwd」快取輸入隨機密碼的時候並沒有提前檢查「passwd」的容量是否足夠。所以,如果使用者輸入乙個足夠造成快取溢位並且重寫「flag」變數預設值所存在位置的記憶體的長「密碼」,即使這個密碼無法通過驗證,flag驗證位也變成了非零,也就可以獲得被保護的資料了。雖然上面的密碼並不正確,但我們仍然可以通過快取溢位繞開密碼安全保護。要避免這樣的問題,建議使用 strncpy()函式。但一些編譯器會在內部檢測棧溢位的可能,所以這樣往棧裡儲存變數很難出現棧溢位。比如gcc中就要使用編譯命令『-fno-stack-protector』來實現上述方案。
問:下面的**能 編譯通過嗎?如果能,它有什麼潛在的問題嗎?
#includevoid main(void)
else
return;
}
答:這道題是我一直想給大家說的,因為main()方法的返回型別,這段**的錯誤在大多數編譯器裡會被當作警告。main()的返回型別應該是「int」而不是「void」,好多人都習慣寫成void,因為「int」返回型別會讓程式返回狀態值。這點非常重要,特別當程式是作為依賴於程式成功執行的指令碼的一部分執行時,所以強烈建議大家以後要寫int。
問:下面的**會導致記憶體洩漏嗎?
#includevoid main(void)
else
return;
}
答:儘管上面的**並沒有釋放分配給「ptr」的記憶體,但並不會在程式退出後導致記憶體洩漏。在程式結束後,所有這個程式分配的記憶體都會自動被處理掉。但如果上面的**處於乙個「while迴圈」中,那將會導致嚴重的記憶體洩漏問題!
問:下面的程式會在使用者輸入』freeze』的時候出問題,而』zebra』則不會,為什麼?
#includeint main(int argc, char *ar**)
else if(argc == 1)
else
if(*ptr == 'z')
free(ptr);
} return 0;
}
答:這裡的問題在於,**會(通過增加「ptr」)修改while迴圈裡「ptr」儲存的位址。當輸入「zebra」時,while迴圈會在執行前被終止,因此傳給free()的變數就是傳給malloc()的位址。但在「freeze」時,「ptr」儲存的位址會在while迴圈裡被修改,因此導致傳給free()的位址出錯,也就導致了seg-fault或者崩潰。
問:在下面的**中,atexit()並沒有被呼叫,為什麼?
#includevoid func(void)
int main(void)
答:這是因為_exit()函式的使用,該函式並沒有呼叫atexit()等函式清理。如果使用atexit()就應當使用exit()或者「return」與之相配合。
問:你能設計乙個能接受任何型別的引數並返回interger(整數)結果的函式嗎?
答:如下:
int func(void *ptr)
如果這個函式的引數超過乙個,那麼這個函式應該由乙個結構體來呼叫,這個結構體可以由需要傳遞引數來填充。
問:下面的操作會輸出什麼?為什麼?
#includeint main(void)
答:輸出結果應該是這樣:
[l]
[i]
因為「++」和「*」的優先權一樣,所以「*ptr++」相當於「*(ptr++)」。即應該先執行ptr++,然後才是*ptr,所以操作結果是「l」。第二個結果是「i」。
問:下面的**段有錯,你能指出來嗎?
#includeint main(void)
答:這是因為,通過*ptr = 『t』,會改變記憶體中**段(唯讀**)「linux」的第乙個字母。這個操作是無效的,因此會造成seg-fault或者崩潰。
問:下面**有問題嗎?如果有,該怎麼修改?
#includeint* inc(int val)
int main(void)
答:儘管上面的程式有時候能夠正常執行,但是在「inc()」中存在嚴重的漏洞。這個函式返回本地變數的位址。因為本地變數的生命週期就是「inc()」的生命週期,所以在inc結束後,使用本地變數會發生不好的結果。這可以通過將main()中變數「a」的位址來避免,這樣以後還可以修改這個位址儲存的值。
問:下面**會輸出什麼?
#includeint main(void)
答:輸出結果是:
110..40..60
這是因為c語言裡函式的引數預設是從右往左處理的,輸出時是從左往右。 C語言測試題
1 c程式的入口 a switch b if c main d getchar 2.c語言中,整數型別中的浮點型別,常用的關鍵字是 a int b char c short d float 3.輸出整數型別的格式符是 a d b c c x d o 4.輸出浮點型別的格式符是 a c b o c d...
C語言 幾個測試題
預處理器 preprocessor 1.用預處理指令 define 宣告乙個常數,用以表明1年中有多少秒 忽略閏年問題 define seconds per year 60 60 24 365 ul 我在這想看到幾件事情 1.define 語法的基本知識 例如 不能以分號結束,括號的使用,等等 2....
C語言測試題07
結構體 自定義複雜 復合型別 由其他基本型別構成 普通型別的缺點 int char 變數之間是沒有關係 結構體描述了一種構成關係 所屬關係 定義乙個結構體型別 描述了學生結構體的構成 型別名是 struct student struct student 給結構體起別名 struct student ...