为什么释放calloc'ed内存会导致我的VC6项目崩溃?
比较这两个基本相同的功能。首先,使用_alloca分配buff
的内存。这工作正常。在第二个中,使用calloc和free来代替_alloca。这崩溃了。为什么释放calloc'ed内存会导致我的VC6项目崩溃?
奇怪的是,我用的是释放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。我建议检查任何内存分配函数的结果与NULL。如果它是NULL,则打印一条消息,然后退出(1)。
_alloca
返回堆栈内存,所以跺脚过去它的结束未必覆盖重要的东西。写入超过堆内存分配的结尾将更可能覆盖重要的内容。
您的代码不会确保缓冲区至少与一样大,将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零字节,并且免费不喜欢它。在上面的代码中,res
实际上包含mpz_sizeinbase
可以使用的东西。
核心转储说什么?或者你没有得到一个? – hhafez 2009-03-04 05:00:27
BTW,_alloca已过时,使用_malloca代替 – 2009-03-04 05:03:16