使用Str(n)cat的卵石堆损坏

使用Str(n)cat的卵石堆损坏,c,heap,pebble-watch,heap-corruption,cloudpebble,C,Heap,Pebble Watch,Heap Corruption,Cloudpebble,在更新Pebble watchface的电池显示时,我将电池电量设置为int s_battery_level,通过我的toString函数运行它(它100%工作,我已经测试过了),然后添加一个%和一个空终止符,这只是为了更好地测量。然而,由于某种原因,当该行运行时,当电池从100%下降到90%(或从100下降到任何较低的数字)时,我会得到一个堆损坏错误。我尝试删除/添加空终止符,同时使用strcat()和strncat(),甚至逃逸了%,但似乎没有任何效果。一旦我删除了这条令人不快的线,它就会完

在更新Pebble watchface的电池显示时,我将电池电量设置为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;
}
char*toString(int值,char*result){
整数位数=位数(值);
结果=calloc(数字+1,sizeof(字符));
结果[位数]='\0';
int usedVal=0;
对于(int i=数字;i>0;i--)
{
int x=(value-usedVal)/pwrOf10(i-1);
结果[数字-i]=(字符)x+'0';
usedVal=usedVal+(结果[数字-i]-“0”)*pwrOf10(i-1);
}
返回结果;
}
整数位数(整数n){
如果(n<0)返回数字((n==0)?9999:-n);
如果(n<10)返回1;
返回1+位(n/10);
}
内部pwrOf10(内部电源){
int-val=1;
int i=功率;
而(i>0)
{
val*=10;
我--;
}
返回val;
}

您正在为
lvl
分配内存两次-一次在
电池更新过程中,然后再次在
toString
中。这是第二次出现问题,因为它只为数字分配了足够的空间

然后你就不能
释放
任何一块内存,所以你也有内存泄漏


至于如何修复它,为什么不直接用sprintf(lvl,%d%%,s_电池电量)
替换对
toString
的调用,然后记住调用
free(lvl)
在功能结束时。

您正在为
lvl
分配内存两次-一次在
电池更新过程中,然后在
到字符串中。这是第二次出现问题,因为它只为数字分配了足够的空间

然后你就不能
释放
任何一块内存,所以你也有内存泄漏


至于如何修复它,为什么不干脆用sprintf(lvl,%d%%,s_battery_level)
替换对
toString
的调用,然后记住在函数末尾调用
free(lvl)

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

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

toString()
精确地分配了它所使用的字节数,因此没有额外的空间可以通过
strcat()追加任何内容。您可以使用
realloc()
增加
lvl
的大小,最后您必须
free()
它以避免内存泄漏。
toString()
的第二个参数
char*result
毫无意义,因为您正在执行
result=calloc(…)
@squemishossifrage数字6代表3位数字,%代表\0,1代表以防万一。@IngoLeonhardt啊,好的。另外,第二个参数没有什么意义,但我加入了它,因为当我尝试在没有第二个参数的情况下编译时,它会给出一个错误(或者可能是一个警告),说明它是如何返回私有变量的。
toString()
精确地分配了它所使用的字节数,因此没有额外的空间可以通过
strcat()追加任何内容。
。您可以使用
realloc()
增加
lvl
的大小,最后您必须
free()
它以避免内存泄漏。
toString()
的第二个参数
char*result
毫无意义,因为您正在执行
result=calloc(…)
@squemishossifrage数字6代表3位数字,%代表\0,1代表以防万一。@IngoLeonhardt啊,好的。另外,第二个参数没有什么意义,但我加入了它,因为当我尝试在没有第二个参数的情况下编译时,它会给出一个错误(或者可能是一个警告),说明它是如何返回私有变量的。这是可行的,但不幸的是,由于某些原因,Pebble SDK不支持sprintf。这是可行的,但不幸的是,出于某些原因,Pebble SDK不支持sprintf。