cmemory-managementreallocpebble-sdk

Pebble crashes on `realloc`, but only in a certain function


I'm using a custom vector in a Pebble app. Pebble is crashing on the call to realloc.

main.c

#include <pebble.h>
#include "movement.h"

static PointArray point_array;

int main(void) {;
    point_array_create(&point_array, 1);
    GPoint point1 = (GPoint){.x = 1, .y = 1};
    GPoint point2 = (GPoint){.x = 2, .y = 2};
    GPoint point3 = (GPoint){.x = 3, .y = 3};

    point_array_push(&point_array, point1);
    point_array_push(&point_array, point2);
    point_array_push(&point_array, point3);
    APP_LOG(APP_LOG_LEVEL_DEBUG, "Done\n");
}

movement.c

#include "movement.h"
#include "pebble.h"


static void point_array_resize(PointArray *point_array){
  point_array->capacity *= 2;
  size_t new_size = point_array->capacity * sizeof(GPoint) + sizeof(GPoint);
  point_array->points = (GPoint*)realloc(point_array->points, new_size);
}


void point_array_create(PointArray *arr, int capacity) {
    arr->points = (GPoint*)malloc(capacity * sizeof(GPoint));
    arr->length = 0;
    arr->capacity = capacity;
}

void point_array_push(PointArray *point_array, GPoint point) {

  APP_LOG(APP_LOG_LEVEL_DEBUG, "pushing");

  if (point_array->length > point_array->capacity) {
    APP_LOG(APP_LOG_LEVEL_DEBUG, "resizing");
    point_array_resize(point_array);
    APP_LOG(APP_LOG_LEVEL_DEBUG, "successful resize");
  }
  point_array->points[point_array->length] = point;
  point_array->length++;
  APP_LOG(APP_LOG_LEVEL_DEBUG, "+ length");
}

movement.h

#include <pebble.h>
#include <stdlib.h>
#include <math.h>

typedef struct {
  GPoint *points;
  int length;
  int capacity;
} PointArray;

void point_array_create(PointArray *arr, int capacity);

void point_array_push(PointArray *point_array, GPoint point);

void point_array_destroy(PointArray *point_array, GPoint point);

GPoint move(GPoint point, float distance, float degrees);

The logs show that the app is crashing at the call to realloc:

[DEBUG] movement.c:20: pushing
[DEBUG] movement.c:29: + length
[DEBUG] movement.c:20: pushing
[DEBUG] movement.c:29: + length
[DEBUG] movement.c:20: pushing
[DEBUG] movement.c:23: resizing

Here's what I tried:


Solution

  • In point_array_push, you test if you need to resize your points at the top, but the test is wrong. You only resize if the length has exceeded capacity, which means you have already overrun your array.

    Instead, check to see if the length has reached capacity.

      if (point_array->length == point_array->capacity) {
        APP_LOG(APP_LOG_LEVEL_DEBUG, "resizing");
        point_array_resize(point_array);
        APP_LOG(APP_LOG_LEVEL_DEBUG, "successful resize");
      }