Frage

Vergleichen Sie diese beiden Funktionen weitgehend identisch. Im ersten wird der Speicher für buff mit _alloca zugeordnet. Dies funktioniert gut. In der zweiten, calloc und frei anstelle von _alloca verwendet. Dieser stürzt.

Die seltsame Sache ist, dass ich die calloc / freie Technik in fast allen anderen GMP Umwicklungsfunktion verwenden ich habe und sie alle arbeiten. Hier tun sie es nicht. Irgendwelche Ideen?

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;
}
War es hilfreich?

Lösung

In

Protokollierung und Dump alles auf dem Weg zu finden, was schief geht. Dies ist in der Regel effizienter als zu versuchen zu erraten.

Andere Tipps

Es kann nicht verwendet sein, aber diese Art von „arbeitet eine Möglichkeit, aber nicht die anderen“ gibt oft einen Fehler, der nur zufällig in einer Situation quietschen durch verursacht aber einen fatalen Fehler in einem anderen.

Wenn Sie vermuten, eine Speicherüberschreibung auftreten können Sie könnten versuchen, ein zusätzliches 8-Bytes in dem Puffer Aufteilung und Schreiben 4-Byte-Starts und sentinels zu beenden, die Sie dann überprüfen, bevor zu befreien.

Ich habe einmal in der Woche versuchen, eine ähnliche Sache, um herauszufinden. Es war ein Pufferüberlauf, der die Zeiger so frei trashed wurde in den Wald geht aus. Rational purify gefunden, das Problem in einer Minute.

calloc könnte möglicherweise NULL zurückgeben, wenn es ein Fehler (wie Mangel an Speicher). Ich würde empfehlen, das Ergebnis jeder Speicherzuordnungsfunktion gegen NULL zu prüfen. Wenn es NULL ist, wird eine Meldung drucken und dann die Ausfahrt (1).

_alloca kehrt Stapelspeicher, so stampft über das Ende der es nicht unbedingt etwas Wichtiges überschreiben kann. Das Schreiben über das Ende eines Haufens Speicherzuweisung wird eher überschreiben etwas Wichtiges.

Ihr Code tut nichts, um sicherzustellen, dass der Puffer mindestens so groß ist wie res zu nach dem Teil n1 durch n2 formatiert werden würde (oder umgekehrt, wie ich weiß nicht, was die eigentliche Funktion des Fall ist); es stellt nur sicher, dass es genügend Speicher für eine initialiazed res hat, die wahrscheinlich 1. ist Wenn n1/n2 mehr Stellen als die hat, crashville begrüßen zu können.

@johnny wies darauf hin, etwas eher peinlich, die eine Überarbeitung des Code erforderlich. (Hier ist, wo ein Kommentar in der Lage zu kreuzen wäre nützlich.)

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;
}

In den vorangegangenen Verkörperungen wurde der Speicher nach an dem Punkt auf den Wert von res in dem Code zugeordnet ist, wo er Null enthalten. So habe ich versucht, Null-Bytes und frei calloc mochte es nicht. In dem obigen Code, res enthält tatsächlich etwas, das mpz_sizeinbase arbeiten kann.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top