realloc正在覆盖数据

时间:2016-11-18 23:13:39

标签: c

我正在尝试重新分配拥有一些数据的char ptr。重新分配到大于当前的大小后,部分数据将被覆盖。

代码的相关部分如下:

char *convertToBinary(char *src, int *fractionPosition, bool double_precision) {
    char *res = (char*)malloc(sizeof(char));
    int currentResultPos = 0, precision;
    int power = (strlen(src) - ((*fractionPosition) + 1)) * (-1);
    float decimalValue_i = convertToInt(src, 10, 0, (*fractionPosition) - 1, 0);
    float decimalValue_f = convertToInt(src, 10, (*fractionPosition) + 1,
                                        strlen(src) - 1, power);

    precision = determinePrecision(double_precision);
    res = fromDecimalToDstinationBase(res, &currentResultPos, 2, 
                                      decimalValue_i, &firstBinaryDigit);
    res = convertFractionIntoResult(res, currentResultPos, 2, 
                                    decimalValue_f, precision);
    *fractionPosition = currentResultPos - 1;

    return res;
}

char *fromDecimalToDstinationBase(char *res, int *resPos, unsigned int dstB,
                                  int decimalValue, char *firstDigit) {
    int valueLength, sum = 0, power = 0;

    while (decimalValue != 0) {
        sum += (decimalValue % dstB) * pow(10, power++);
        decimalValue /= dstB;
    }
    valueLength = countDecimalDigits(sum);
    res = copyIntToStr(res, sum, resPos, valueLength);
    return res;
}

char *copyIntToStr(char* res, int sum, int *resPos, int power) {
    int remainder;
    bool flag = true;
    res = (char*)calloc(power + (*resPos) + 1, sizeof(char));
    power--;
    while (sum != 0) {
        if (res[0] == '1' && flag) {
            addFractionPoint(res, resPos);
            flag = false;
        }
        remainder = sum % (int)pow(10, power);
        res[(*resPos)++] = (sum / pow(10, power--)) + '0';;
        sum = remainder;
    }
    res[*resPos] = '\0';
    return res;
}

char *convertFractionIntoResult(char *res, int logicalS, unsigned int dstB,
                                float decimalValue, unsigned int precision) {
     //here, logicalS = 5
     int physicalS = logicalS, resRemainderCounter = 0;
     float remainder = decimalValue;

     // here, res = "1.101"
     while (resRemainderCounter != precision) {
        if (physicalS == logicalS) {
            physicalS *= 2;
            res = (char*)realloc(res, physicalS * sizeof(char)); 
            // now, res = "1.1ÍÍÍÍÍÍÍýýýý"
        }

我全神贯注地寻找解释。有谁知道为什么会这样?我可能做错了什么?

修改

另外,我试图用一些随机的非常大的数字替换物理,并且它没有改变任何东西。

2 个答案:

答案 0 :(得分:2)

看起来你正在使用微软的编译器和库。在调试模式下,库会使用各种值来填充未初始化的内存部分,这些值在调试时会突出显示,以帮助您检测错误。

您看到的Í对应于0xCD,这是库用于标记堆内存的未初始化部分的值。 ý对应于0xFD,库用于标记堆分配末尾之外的区域。维基百科可以告诉你很多关于这些magic numbers的内容。

让我们来看看你的代码:

// here, res = "1.101"
// ...
physicalS *= 2;
res = (char*)realloc(res, physicalS * sizeof(char)); 
// now, res = "1.1ÍÍÍÍÍÍÍýýýý"

如果可以,realloc应该返回至少所请求大小的缓冲区。它可以是原始缓冲区,扩展,也可以是新缓冲区。如果它是新缓冲区,并且新缓冲区大于原始缓冲区,则应将原始内容复制到新缓冲区。该库的调试版本将使用0xCD填充新缓冲区的其余部分。

因此,这个结果告诉我,当您认为res指向"1.101"时,它实际指向包含1.1的未终止缓冲区,恰好跟随01可能是缓冲区溢出的结果。

然后你要求一个更大的缓冲区,1.1被忠实地复制到开头,然后调试库用0xCD字节填充新缓冲区的剩余部分,以表明它是未初始化的堆内存。 / p>

在这种情况下,我会使用调试器来监视每个malloc和realloc的实际缓冲区大小,并检查代码是否实际覆盖了缓冲区的末尾。

答案 1 :(得分:-1)

发现错误!

当调用addFractionPoint(res, resPos)时,已经进行了另一次重新分配,这比在该呼叫之前进行的重新分配要小。

感谢大家的评论。