比较这两个基本相同的功能。在第一个中,使用_alloca分配 buff 的内存。这很好用。在第二种情况下,使用calloc和free代替_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字节的开始和结束标记,然后在释放之前检查它们。

我曾经花了一周的时间试图弄清楚类似的事情。这是一个缓冲区溢出,破坏了指针所以自由进入了树林。 Rational purify在一分钟内发现了这个问题。

如果出现错误(例如内存不足),

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 的值进行分配的。因此,我试图calloc零字节和free不喜欢它。在上面的代码中, res 实际上包含 mpz_sizeinbase 可以使用的东西。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top