2012-01-28 9 views
2

私は他の誰かのコードをデバッグしようとしています。深刻だと思われるグローバル配列を処理する特定の方法を見つけましたが、最初にそれを使用した人はそれを誓います。 私はそれに対して議論を見つける必要があります。 ここに簡略化されたコードがあります(これは元のコードではなく、抽象版です)。静的intポインタに対する引数

私の質問:どのような議論をするでしょうか?

int test(int i, int v, int type, int** t) 
{ 
    static int *teeest; 
    int result = 0; 
    switch(type) 
    { 
     case (1): 
      { 
       int testarr[i]; 
       teeest = testarr; 
      } 
     break; 
     case (2): 
      result = teeest[i]; 
     break; 
     case (3): 
      teeest[i] = v; 
     break; 
    } 
    if (t != NULL) 
    { 
     *t = teeest; 
    } 
    return result; 
} 

int main() 
{ 
    int *te = (int*)1; 
    test(5, 0, 1, &te); 
    printf("%p\n", te); 
    int i=0; 
    for(;i<5;i++) 
    { 
     test(i, i, 3, NULL); 
     printf("Value: %d\n", test(i,0,2, NULL)); 
    } 
    return 0; 
} 
+0

は、グローバル配列よりも悪いです。関数呼び出しのオーバーヘッドがそのアクセスに追加されるためです。 –

+0

これを書いた人は誰でも同等のもの、あるいは少なくともブラックハット部門に移管されていなければなりません。これは実際に実装の詳細に依存するこのような凶悪なハックが有用であるためです。 –

+0

私はいつもあなたが5人の開発者に尋ねることができるときに実装について笑います。そして、すべての単一の開発者は、コードが悪い考えである別の理由を与えます。なぜコードが悪いのかについて全員が同意できない場合でも、すべてが同意しないと同意できない場合は、それは悪いです。それは本当にそれを修正する時間です。 –

答えて

3

ローカル変数は、宣言されたブロックの後では無効です。したがって、このコードは未定義の動作です。アクセスするすべてのランダムなアドレスと同様に、動作する可能性がありますが、動作しない可能性もあります。

int testarr[i]の代わりにmallocを使用して(以前の配列を解放してteeestを初期化することが心配です)、正しいことに注意してください。このコードの問題は、静的ポインタについては何も持っていません。

+0

それを書いた人は、コンパイラがこれを認識して、私が頼りにするのは全く怒っていると思っているものを、どちらも等しく扱うと言った。ご回答有難うございます。 – user1159208

+0

@ user1159208 - いいえ、コンパイラはそれを処理しません。 – Dirk

2

これは本当に悪いことです。ポインタが静的であるという理由だけで、ポインタが指すデータが周囲にあることを意味するわけではありません。たとえば、関数が終了するとtestarrが消え、返されたポインタを使うと、ドラゴンが表示されることがあります。

2

このスタイルの大きな打撃は、スタック上にあるローカル宣言された配列にアクセスしているという事実を隠していることです。それから、あなたはスタックへのポインタを保持します。スタックへのポインタは呼び出しごとに保持され、各呼び出しごとにスタックが異なります。

私が考えていたもう一つのことは、データ構造が何であるかを開発者から隠してしまったことです。配列のインデックス付けは通常の操作です。ポインタをインデックスすることにより、それが配列であり、より複雑なデータ型ではないことを認識させることができます。これはまた、境界チェックに混乱を与えます。

1

もう1つのことは、グローバル変数のすべての短所が直接適用されることです。コードはリエントラントではなく、スレッドセーフではありません(懸念がある場合)。

関連する問題