2010-11-18 52 views
3

我有簡單的測試程序在Linux上sprintf的錯誤用法?

#include <stdio.h> 
int main(int argc , char* argv[]) 
{ 
    unsigned int number=2048; 

    char* cpOut; 
    char cOut[4]; 
    cpOut=(char*)&cOut[0]; 
    printf("cOut address= %x \n",&cOut[0]); 
    printf("cpOut address = %x \n",cpOut); 

    sprintf(&cOut[0],"%d \n", number); 

    printf("cOut address= %x \n",&cOut[0]); 
    printf("cpOut address = %x \n",cpOut); 
}; 

試運行,GCC 4.3.4:在Solaris 10

[email protected] /tmp $ ./a.out 
cOut address= f9f41880 
cpOut address = f9f41880 
cOut address= f9f41880 
cpOut address = f9f41880 

試運行,太陽C++ 5.10:

bash-3.00$ ./a.out 
cOut address= 8047488 
cpOut address = 8047488 
cOut address= 8047488 
cpOut address = 8000a20 

任何人都可以請解釋爲什麼通過調用sprintf函數覆蓋指針cpOut?

回答

3

我認爲這是一個緩衝區溢出的情況。嘗試使COUT較大,也更安全的替代snprintf的sprintf的:

sprintf(&cOut[0],"%d \n", number); 

應改爲

snprintf(cOut,sizeof(cOut),"%d \n", number); 
+1

非常感謝回答 – jano 2010-11-18 15:58:06

6

由於字符串"2048 \n"不適合char cOut[4];,你要創建一個緩衝區溢出。

+1

非常感謝您的回答 – jano 2010-11-18 15:56:44

4

您正在將7個字節(「2048 \ n」+ NUL)寫入堆棧中大小爲4的數組中。這將覆蓋堆棧中3個字節的任何低於它的值,在本例中爲cpOut。新值cpOut向您顯示:第一個字節不變爲0x08,然後接下來的3個字符串是您正在編寫的字符串的最後三個字節:00(NUL),0a('\ n'),20('' )。

+1

非常感謝回答 – jano 2010-11-18 15:57:30

1

這一行:

sprintf(&cOut[0],"%d \n", number); 

寫入7個字符: 「2048 \ n \ 0」,但只對它們中的4空間。值0x8000a20包含(相反順序):空格,換行和字符0.

+1

非常感謝回答 – jano 2010-11-18 15:58:30