0

これら 2 つのほぼ同一の関数を比較します。最初に、buff_alloca を使用してメモリが割り当てられます。これはうまくいきます。2 番目の例では、_alloca の代わりに calloc と free が使用されています。これはクラッシュします。

奇妙なことは、私が持っている他のほぼすべての 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;
}
4

6 に答える 6

1

ログを追加し、途中ですべてをダンプして、何が問題なのかを見つけます。これは通常、推測を試みるよりも効率的です。

于 2009-03-04T05:13:49.547 に答える
1

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

于 2009-03-04T05:17:15.793 に答える
1

私はかつて、同様のことを理解しようとして1週間を費やしました。ポインターを破棄したのはバッファー オーバーランであり、フリーは森の中に消えていました。Rational Purify はすぐに問題を発見しました。

于 2009-03-04T05:05:53.217 に答える
0

_allocaはスタック メモリを返すため、スタック メモリの最後を踏み越えても、必ずしも重要なものが上書きされるとは限りません。ヒープ メモリ割り当ての最後を超えて書き込むと、重要なものが上書きされる可能性が高くなります。

あなたのコードは、resn1 を n2 で除算した後にフォーマットされるのと同じ大きさのバッファーであることを保証するために何もしません (実際の関数が何をするかわからないため、その逆も同様です)。resおそらく1である初期化された に十分なメモリがあることを保証するだけです。n1/n2それよりも多くの桁がある場合は、crashvilleへようこそ。

于 2009-03-04T22:18:57.430 に答える