2011-10-30 11 views
3

私は初心者のプログラマですが、通常は自分の問題を解明することができます。今回私はこの問題を解決しましたが、それでも私は悩みます。友人は私がこのコミュニティに入力を求めると提案しました。sprintfバッファサイズ

私はCで数値を印刷しようとしています。私はsprintfを使ってこれを行う関数を持っています。私は2文字のバッファを使用するので、数値は2桁を超えることはありません。なぜかこれは私のロジックが失敗するところです。これは、sprintfに渡される変数の1つを変更することによって無限ループを引き起こしますが、バッファサイズを増やすことで問題が解決されます。

ここ失敗コードは次のとおり

#include <stdio.h> 

void printarray(int array[][4]) { 
    int y; 
    int z; 
    char buf[2]; 
    for (y=0; y<4; y++) { 
    for (z=0; z<4; z++) { 
     sprintf(buf, "%d", array[y][z]); 
     printf("buf is %s, y is %d and z is %d\n",buf,y,z); 
    } 
    } 
} 

int main() { 
    int arr[4][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0} }; 

    printarray(arr); 

    return 0; 
} 

とすぐyは2になるように、それはバック0にリセットされる。従って、無限ループ。 buf [2]をbuf [8]に変更することで問題が解決されます。

+2

bufがオーバーフローしたときに無限ループが発生するのは、sprintfがbuf [2]を '\ 0'に設定しているためです。スタック上でbufの後にz(リトルエンディアンで)が続く可能性があります。したがって、zの下位バイトは0に設定され、高位バイトがすでに0であったたびにzを0に設定します。 – jstanley

答えて

11

あなたはNULターミネーターを忘れています。はCで、stringsは、ターミネータのための余分な文字を必要とするので、char buf[2]は10と99ちなみに

の間の数字に対応するためにchar buf[3]をあるべき、あなたのコードは、出力バッファを過ぎて書き込み、有効にすることができますようsprintfが危険である理由を示していますstack smashing attacks。より良いオプションはsnprintfです。

3

C文字列はNULLで終了します。 2文字(「10」など)がある場合は、ヌルターミネータに2 + 1サイズのバッファが必要です。

sprintf()これをバッファの最後に追加します。現在のケースでは、十分なスペースを確保していないため、実際にはバッファオーバーフローが発生します。

最近のより安全なアプローチは、バッファの長さを指定するsnprintf()を使用することです。

2

sprintfは、生成された文字列の最後に\0を追加するとします。たとえば、番号99を印刷すると、バッファに"99\0"が入るため、長さが2のバッファで問題が発生します。