سؤال

وقارن هذه ظيفتين متطابقة إلى حد كبير. في المرحلة الأولى، يتم تخصيص الذاكرة لbuff باستخدام _alloca. هذا يعمل بشكل جيد. في الثاني، calloc وخالية تستخدم بدلا من _alloca. هذا تعطل.

والشيء الغريب هو أنني استخدام تقنية calloc / مجانا تقريبا في كل وظيفة GMP التفاف أخرى لدي وأنهم جميعا العمل. هنا لم يفعلوا ذلك. أي أفكار؟

تحليل 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;
}
هل كانت مفيدة؟

المحلول

واضافة قطع الأشجار وتفريغ كل شيء على طول الطريق للعثور على ما يذهب على نحو خاطئ. هذا هو عادة ما تكون أكثر فاعلية من محاولة تخمين.

نصائح أخرى

قد يكون لا علاقة لها، ولكن هذا النوع من "يعمل في اتجاه واحد ولكن ليس الآخر" غالبا ما يشير إلى الخلل الذي يحدث لمجرد أن صرير من قبل في حالة واحدة ولكن تسبب خطأ فادح في بلد آخر.

إذا كنت تشك في الكتابة الذاكرة قد يحدث قد تتمكن من محاولة تخصيص اضافي 8 بايت في المخزن المؤقت والكتابة بداية 4 بايت وإنهاء الحراس الذي ثم تحقق من قبل الافراج.

وقضيت مرة واحدة في الاسبوع في محاولة لمعرفة شيء مماثل. كان تجاوز سعة المخزن المؤقت الذي الحضيض مؤشر ذلك مجانا والخروج إلى الغابة. وجدت تنقية عقلانية القضية في دقيقة واحدة.

وcalloc يحتمل أن تعود فارغة إذا كان هناك خطأ (مثل نقص الذاكرة). أوصي التحقق من نتيجة أي وظيفة تخصيص الذاكرة ضد NULL. إذا كانت فارغة، طباعة الرسالة ثم الخروج (1).

وعوائد _alloca كومة الذاكرة، لذلك الدوس بعد نهاية قد لا الكتابة بالضرورة شيئا مهما. سوف يكتب بعد نهاية تخصيص الذاكرة كومة من المرجح الكتابة شيء مهم.

والتعليمات البرمجية الخاصة بك لا يفعل شيئا لضمان أن المخزن المؤقت هو على الأقل كبيرة كما سيتم تنسيق res إلى بعد تقسيم N1 N2 التي كتبها (أو العكس بالعكس، وأنا لا أعرف ما تفعله وظيفة الفعلي)؛ فإنه يضمن فقط أن لديها ذاكرة كافية لres initialiazed، الذي هو على الارجح 1. إذا n1/n2 ديه أرقام أكثر من ذلك، مرحبا بكم في crashville.

وأشار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 عند نقطة في التعليمات البرمجية حيث أنها تحتوي على صفر. وهكذا كنت أحاول أن calloc بايت الصفر وخالية لم ترغب في ذلك. في رمز أعلاه، res يحتوي في الواقع شيئا mpz_sizeinbase يمكن التعامل معها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top