一個printf函數引發的死機

 今天同事解決了一個問題,頗有啓發,拿出來共賞之。

大家都熟知printf函數,有%s、%d、%p、%u等等參數,當然你也可以直接printf("某某字符串"),或者:

char str[] = "xxxxxx";
printf(str);

如果這樣寫,會編譯不過:

printf("str = %s\n");

因為參數不夠。

可是你有沒有考慮過下面這種情況?

char str[] = "im a good man %s\n";
printf(str);

這段代碼是可以編過并運行的,但是。。。它似乎又有點問題。

很容易看出printf在解析字符串時會發現有個%s,於是它會試圖用後面一個參數替換%s,可是哪兒來的後面的參數呢?

printf函數當但不知道,它以為有,所以就按“慣例”行事,在x86上它會到堆棧里找,本來我們只壓入了str一個參數,cpu會往上找,它認為str下面的那個就是這個參數,於是毫不猶豫的拿去用。。。可是那可能是別的什麼東西,比如壓在棧里的IP、EBP什麽的,這樣就出錯了。如果它取的這個值是個不可訪問的內存,程序就完蛋。在PPC上CPU會使用R4寄存器,情況也是相同的,誰知道R4裏面是什麼東西!

 

大多情況下沒有程序員會這樣寫,但一旦我們的printf里帶的是變量的時候就要多考慮考慮了。比如我們要輸出用戶輸入的字符串或一段密文,那麼這裡面的東西可能是不可控的,可能就會有類似%s、%d之類的東西。 需要做限定或轉義。

 

現在回想起來以前在hw數通的時候爲什麽不讓直接用printf,是有考慮的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值