0

在更新 Pebble 表盘的电池显示时,我将电池电量设置为 int s_battery_level,通过我的 toString 函数运行它(它在 100% 的时间内有效,我已经对其进行了测试),然后附加一个 % 和一个空终止符,只是为了很好的衡量。但是,由于某种原因,当该行运行时,当电池从 100% 下降到 90%(或 100 到任何低位数字)时,我会收到一个堆损坏错误。我尝试在空终止符中删除/添加,同时使用 strcat() 和 strncat(),甚至转义 %,但似乎没有任何效果。一旦我删除了违规行,它就可以完美运行。

为什么这条线会破坏堆?并且可选地,我该如何修复/避免它?

static void battery_update_proc(Layer *layer, GContext *ctx) {
  graphics_context_set_text_color(ctx, TxtColor);
  char * lvl = calloc(6,sizeof(char));
  lvl = toString(s_battery_level, lvl);
  //strncat(lvl, "%\0", 2);
  //offending line above ^
  APP_LOG(APP_LOG_LEVEL_DEBUG, "%s", lvl);
  graphics_draw_text(ctx, lvl, s_txt_font, GRect(bound.origin.x + ROUND_OFFSET_BA_X, bound.size.h * .5 + ROUND_OFFSET_BA_Y, bound.size.w, 24), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);
}

为了更好地衡量,这里是 toString 函数:

char * toString(int value, char * result) {
    int digit = digits(value);
    result = calloc(digit + 1, sizeof(char));
    result[digit] = '\0';
    int usedVal = 0;
    for (int i = digit; i > 0; i--)
    {
        int x = (value - usedVal) / pwrOf10(i - 1);
        result[digit - i] = (char) x + '0';
        usedVal = usedVal + (result[digit - i] - '0') * pwrOf10(i - 1);
    }
    return result;
}

int digits(int n) {
    if (n < 0) return digits((n == 0) ? 9999 : -n);
    if (n < 10) return 1;
    return 1 + digits(n / 10);
}

int pwrOf10(int power) {
    int val = 1;
    int i = power;
    while (i > 0)
    {
        val *= 10;
        i--;
    }
return val;
}
4

2 回答 2

3

您分配内存lvl两次 - 一次 in battery_update_proc,然后再次 in toString。这是第二次出现问题,因为它只为数字分配了足够的空间。

然后你没有freeing 任何一块内存,所以你也有内存泄漏。

至于如何修复它,为什么不将调用替换为toStringsprintf(lvl,"%d%%",s_battery_level)然后记得free(lvl)在函数末尾调用。

于 2017-08-02T16:13:58.753 回答
0

这个问题的最终答案是我必须修改 toString 以在 calloc() 调用中添加额外的空间。感谢所有让我想起技术性的人!

于 2017-08-02T17:29:44.327 回答