【问题标题】:Where is the memory error in this code?此代码中的内存错误在哪里?
【发布时间】:2014-12-15 21:01:39
【问题描述】:

有人要求我用 C 语言编写这段代码作为练习。当他们查看我所写的内容时,他们立即告诉我内存管理存在巨大错误。作为一个简单的练习,他们希望我找到并修复这个错误。我的知识一定有差距,或者我一定忽略了一些非常明显的东西,因为我一辈子都找不到它。如果有人能帮我弄清楚,我将非常感激。

代码如下:

char int_to_char(int number){
    if (number > 9) return (char)(((int)'A') + number - 10);
    else return (char)(((int)'0') + number);
}

int change_base(char* output, int buffer_size, int decimal_number, int base){
    //check for valid parameters
    if((base < 2) || (base > 26)) return -1;        //range error

    //ready variables
    int output_i = 0;
    int tmp_string_i = 0;
    int dividend;
    char remainder;
    char * tmp_string = calloc(buffer_size, sizeof(char));
    memset(output, '\0', buffer_size*sizeof(char));

    //check for negative input
    if(decimal_number < 0){
        output[0] = '-';
        dividend = -decimal_number;
        output_i++;
    }
    else dividend = decimal_number;

    //find digits
    while(dividend / base != 0){
        remainder = int_to_char(dividend % base);
        dividend = dividend / base;
        tmp_string[tmp_string_i] = remainder;
        tmp_string_i++;
        if(tmp_string_i + 1 > buffer_size){     //+1 for the extra negative sign
            free(tmp_string);
            return -2;      //buffer size error
        }
    }
    //add last digit to string
    remainder = int_to_char(dividend);
    tmp_string[tmp_string_i] = remainder;

    //copy tmp_string to output in reverse order
    for(; tmp_string_i >= 0; tmp_string_i--){
        output[output_i] = tmp_string[tmp_string_i];
        output_i++;
    }
    free(tmp_string);
    return 0;
}

另外值得注意的是,我已通过 Valgrind 运行此代码以查找任何常见的内存错误,但它没有报告任何错误。我不太了解 Valgrind 的高级功能或细微差别。

最后,我很高兴任何 cmets 能够提高此代码的整体有效性和可读性。

【问题讨论】:

  • “巨大错误”实际上不是很具体(甚至不是客观的),所以你应该问那个人他们认为你的代码有什么问题。我能看到的唯一让我烦恼的是,你没有检查calloc 是否真的成功了。
  • 感谢您的意见。我开始认为他们可能犯了一个错误。另外,我从反对票中感觉到这不是一个很好的问题(哈!)。我应该在 codereview 上发布这个吗?
  • 你真的试过运行代码看看会发生什么吗?
  • 是的,代码审查可能是一个更好的选择,因为 SO 的目标更多是帮助解决特定问题(例如,如果您遇到运行时错误或您无法弄清楚的编译器错误),而不是试图找出错误(甚至是不像人们实际想象的那样明显的“巨大错误”)
  • @Ben Creighton - 如果代码通过了所有单元测试并且代码分析工具没有报告错误,那么提交代码审查是有意义的。例如,calloc 之后的 memset\0 是多余的。

标签: c malloc dynamic-memory-allocation calloc


【解决方案1】:

如果要说一个“巨大的错误”,那么这个错误就是糟糕的代码本身。:)l 因此,如果还有其他错误,那么实际上它们不值得讨论,直到代码被重写。

例如,你知道如果某个整数是负数,那么在这样的语句之后

number = - number;

这个数字可以像以前一样是负数吗?:)

我认为“某人”的意思是“巨大错误”,即您的字符串不是以零结尾的。:) 考虑这样一种情况:数字只有一位且 buffer_size 等于 1

为什么 buffer_size 的类型是 int 而不是 size_t?

在我看来,为这种转换分配额外的缓冲区也是一个坏主意。

【讨论】: