문제

이 두 가지 크게 동일한 기능을 비교하십시오. 첫 번째로, 메모리 buff _alloca를 사용하여 할당됩니다. 이것은 잘 작동합니다. 두 번째로, 콜록과 무료는 _alloca 대신 사용됩니다. 이것은 충돌합니다.

이상한 점은 내가 가지고있는 거의 모든 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;
}
도움이 되었습니까?

해결책

로깅을 추가하고 모든 것을 덤프하여 무엇이 잘못되는지 찾으십시오. 이것은 일반적으로 추측하는 것보다 더 효율적입니다.

다른 팁

관련이있을 수 있지만,이 유형의 "한 가지 방법이지만 다른 방법은 아닙니다"는 종종 한 상황에서 삐걱 거리는 버그를 나타내지 만 다른 상황에서는 치명적인 오류를 일으키는 버그를 나타냅니다.

메모리 덮어 쓰기가 발생할 수 있다고 의심되면 버퍼에 여분의 8 바이트를 할당하고 4 바이트 시작 및 종료 센티넬을 작성하여 자유롭게하기 전에 확인할 수 있습니다.

나는 한 번 비슷한 것을 알아 내려고 일주일을 보냈다. 포인터를 쓰레기를 버린 것은 버퍼 오버런이었다. 합리적 정수는 1 분 안에이 문제를 발견했습니다.

오류가 있으면 (예 : 메모리 부족) Calloc은 잠재적으로 NULL을 반환 할 수 있습니다. NULL에 대한 메모리 할당 함수의 결과를 확인하는 것이 좋습니다. NULL 인 경우 메시지를 인쇄 한 다음 (1)을 종료하십시오.

_alloca 스택 메모리를 반환하므로 끝을 지나서 중요한 것을 덮어 쓰는 것은 아닙니다. 힙 메모리 할당 끝을 지나서 쓰면 중요한 것을 덮어 쓸 가능성이 높습니다.

코드는 버퍼가 최소한 res N1을 N2로 나눈 후 형식화됩니다 (또는 실제 함수가 무엇을하는지 모르기 때문에 그 반대도 마찬가지). 그것은 초기의 메모리에 충분한 메모리를 보장합니다. res, 아마도 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 코드의 지점에서 0이 포함되어 있습니다. 그래서 나는 제로 제로 바이트를 부르려고했고 무료는 그것을 좋아하지 않았다. 위 코드에서 res 실제로 무언가가 들어 있습니다 mpz_sizeinbase 함께 일할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top