2009-03-04 4 views
0

これら2つの機能は大きく異なります。最初に、buffのメモリは_allocaを使用して割り当てられます。これは正常に動作します。 2番目の方法では、_allocaの代わりにcallocとfreeが使用されます。これはクラッシュします。なぜcalloc'edメモリを解放すると私のVC6プロジェクトがクラッシュするのですか?

奇妙なことは、私が持っている他のほとんどすべてのGMPラッピング機能でcalloc/freeテクニックを使用していることです。ここで彼らはしません。何か案は?

1:

#define Z(x) mpz_t (x); mpz_init((x)); 
#define BUFF_SIZE (1024 * 32) 

BSTR __stdcall IBIGDIV(BSTR p1, BSTR p2) { 
    USES_CONVERSION; 

    Z(n1); 
    Z(n2); 
    Z(res); 

    char * buff = (char *) _alloca(mpz_sizeinbase(res, 10) + 2); 

    LPSTR sNum1 = W2A(p1); 
    LPSTR sNum2 = W2A(p2); 

    mpz_set_str(n1, sNum1, 10); 
    mpz_set_str(n2, sNum2, 10); 

    if (mpz_sgn(n2) != 0) { 
     mpz_div(res, n1, n2); 
     mpz_get_str(buff, 10, res); 
    } else { 
     strcpy(buff, "-0"); 
    } 

    BSTR bResult = _com_util::ConvertStringToBSTR(buff); 
    return bResult; 
} 

2:

#define Z(x) mpz_t (x); mpz_init((x)); 
#define BUFF_SIZE (1024 * 32) 

BSTR __stdcall IBIGDIV(BSTR p1, BSTR p2) { 
    USES_CONVERSION; 

    Z(n1); 
    Z(n2); 
    Z(res); 

    char * buff = (char *) calloc(mpz_sizeinbase(res, 10) + 2, sizeof(char)); 

    LPSTR sNum1 = W2A(p1); 
    LPSTR sNum2 = W2A(p2); 

    mpz_set_str(n1, sNum1, 10); 
    mpz_set_str(n2, sNum2, 10); 

    if (mpz_sgn(n2) != 0) { 
     mpz_div(res, n1, n2); 
     mpz_get_str(buff, 10, res); 
    } else { 
     strcpy(buff, "-0"); 
    } 

    BSTR bResult = _com_util::ConvertStringToBSTR(buff); 
    free(buff); 
    return bResult; 
} 
+0

コアダンプとは何ですか?あなたは1つを取得しないでください? – hhafez

+0

ここで、_allocaは非推奨です。代わりに_mallocaを使用します。 –

+0

新しく初期化された構造体で使用されるmpz_sizeinbase()は0を返すはずです。allocaを使用すると、バッファがスタック上にあり、 )。 – johnny

答えて

1

何がうまくいかないのかを見つけるために、すべての方法でロギングとダンプを追加します。これは通常、推測しようとするよりも効率的です。

1

それは無関係であるが、「一つの方法を動作しますが、他ではないが、」多くの場合、ただで鳴き、たまたまバグを示し、この種のことある状況では別の状況では致命的なエラーが発生します。

メモリの上書きが発生している可能性がある場合は、バッファに余分な8バイトを割り当てて、4バイトの開始と終了のセンチネルを書き込んでから解放してから解放してください。

1

私は一度同じようなことを理解しようと1週間過ごしました。それは無料で森に行くようにポインタをゴミ箱に詰め込んだバッファオーバーランでした。合理化された浄化は分で問題を発見しました。

1

エラー(メモリ不足など)がある場合、callocはNULLを返す可能性があります。私は、NULLに対してメモリ割り当て関数の結果をチェックすることをお勧めします。 NULLの場合、メッセージを出力して終了します(1)。

+0

退屈であっても、callocのようなものからの戻り値を常にチェックする必要があります。 – Johan

+0

callocがnullを返した場合、クラッシュはもっと早く発生します。 –

0

_allocaはスタックメモリを返します。そのため、スタックの最後を突き詰めて必ずしも重要なものを上書きしない可能性があります。ヒープメモリ割り当ての最後を過ぎて書くと、重要なものを上書きする可能性が高くなります。

あなたのコードは、バッファが少なくともresがn1でn2で除算された後にフォーマットされることを保証するものではありません(またはその逆でも、私は実際の関数が何をしているか分かりません)。それは初期化されたresのための十分なメモリを持っていることを保証するだけであり、おそらく1です。n1/n2がそれより多くの数字を持っている場合、クラッシュビルへようこそ。

0

@johnnyはコードの書き直しを必要とする、むしろ恥ずかしいものを指摘しました。 (有用であろうコメントをチェックすることができるのはここです。)前の化身で

BSTR __stdcall IBIGDIV(BSTR p1, BSTR p2) { 
    USES_CONVERSION; 

    Z(n1); 
    Z(n2); 
    Z(res); 

    char * buff; 

    LPSTR sNum1 = W2A(p1); 
    LPSTR sNum2 = W2A(p2); 

    mpz_set_str(n1, sNum1, 10); 
    mpz_set_str(n2, sNum2, 10); 

    if (mpz_sgn(n2) != 0) { 
     mpz_div(res, n1, n2); 
     buff = (char *) calloc(mpz_sizeinbase(res, 10) + 2, sizeof(char)); 
     mpz_get_str(buff, 10, res); 
    } else { 
     buff = (char *) calloc(3, sizeof(char)); 
     strcpy(buff, "-0"); 
    } 

    BSTR bResult = _com_util::ConvertStringToBSTR(buff); 
    free(buff); 
    return bResult; 
} 

、メモリは、それがゼロに含まれるコード内のポイントにおけるresの値に応じて割り当てられていました。したがって、私は0バイトのcallocを試していましたが、freeはそれを気に入らなかったのです。上記のコードでは、resには実際にはmpz_sizeinbaseが対応できるものが含まれています。

関連する問題