Ошибка при удалении памяти JSON-объекта (язык Си)

Я пишу парсер для JSON на языке Си (стандарт ANSI C99, компилятор GCC). Всё срабатывает правильно, однако при попытке освободить память программа завершается с кодом -1073740940 (0xC0000374). Эта ошибка срабатывает при наличии в JSON Object-элемента. Вот код:

Структуры хранения объектов

typedef enum {INT, STR, ARR, OBJ} eltype;

typedef struct { //JSON
    eltype type;
    void* data;
} JSON;

typedef struct { //JSONArray
    int len;
    JSON* data;
} JSONArray;

typedef struct { //JSONObject
    int len;
    wchar_t** keys;
    JSON* values;
} JSONObject;

Макросы:

#define sleep for (; **input == ' ' || **input == '\t' || **input == '\n'; (*input)++);

#define STR_ERROR___FILE_OR_LINE_ENDED_BEFORE_STRING_END 1
#define STR_ERROR___CANT_ESCAPE_U_CHARACTER 2

#define INT_ERROR___NUMBER_NOT_FOUND 1
#define INT_ERROR___NUMBER_NOT_FOUND_AFTER_POINT 2
#define INT_ERROR___NUMBER_NOT_FOUND_AFTER_E_CHARACTER 3

Парсер Object-элементов

char parseOBJ (wchar_t** input, JSON* output) {
    output->type = OBJ;

    sleep;
    JSONObject* output_data = malloc(sizeof(JSONObject));
    output_data->keys = malloc(0); output_data->len = 0; output_data->values = malloc(0);
    while (**input != '}') {
        if (**input != '"') {return 1;}
        (*input)++;

        output_data->keys = realloc(output_data->keys, (output_data->len + 1) * sizeof(wchar_t*));
        output_data->values = realloc(output_data->values, (output_data->len + 1) * sizeof(JSON*));

        {
            JSON temp = {STR, NULL}; char l = parseSTR(input, &temp);
            if (l) return l;
            output_data->keys[output_data->len] = temp.data;
        }

        sleep;
        if (**input != ':') {return 2;}
        (*input)++;
        sleep;

        parseJson(input, output_data->values + output_data->len);

        output_data->len++;

        sleep;
        if (**input == ',') {(*input)++; sleep;}
        else if (**input == '}') break;
        else return 3;
    }

    output->data = output_data;
    (*input)++;

    return 0;
}

Общий парсер

char parseJson (wchar_t** input, JSON* output) {
    sleep;

    if (**input == '"') {(*input)++; return parseSTR(input, output);}
    else if (**input == '[') {(*input)++; return parseARR(input, output);}
    else if (**input == '{') {(*input)++; return parseOBJ(input, output);}
    else return parseINT(input, output);

    return 0;
}

Очистка памяти

void freeJSON (JSON input) {
    if (input.type == STR || input.type == INT) {free(input.data);}
    else if (input.type == ARR) {
        JSONArray data = *(JSONArray*) input.data;
        for (int i = 0; i < data.len; i++) {
            freeJSON(data.data[i]);
        }
        free(data.data);
        free(input.data);
    }
    else if (input.type == OBJ) {
        JSONObject data = *(JSONObject*) input.data;
        for (int i = 0; i < data.len; i++) {
            free(data.keys[i]);
            freeJSON(data.values[i]);
        }

        free(data.keys);
        free(data.values);
        free(input.data);
    }
}

Остальные парсеры

char parseSTR (wchar_t** input, JSON* output) {
    output->type = STR; wchar_t* output_data = malloc(0);
    int sz = 0;
    #define write(dt) output_data[sz] = dt;

    for (; **input != L'"'; (*input)++) {
        if (sz % 10 == 0) output_data = realloc(output_data, (sz + 10) * sizeof(wchar_t));

        if (**input == L'\n' || **input == 0) {
            free(output_data);
            return STR_ERROR___FILE_OR_LINE_ENDED_BEFORE_STRING_END;
        } else if (**input == L'\\') {
            (*input)++;
            if (**input == L'"') {write(L'\"');}
            else if (**input == L'\\') {write(L'\\');}
            else if (**input == L'\'') {write(L'\'');}
            else if (**input == L't') {write(L'\t');}
            else if (**input == L'n') {write(L'\n');}
            else if (**input == L'r') {write(L'\r');}
            else if (**input == L'b') {write(L'\b');}
            else if (**input == L'u') {
                wchar_t u = 0;
                for (char i = 0; i < 4; i++) {
                    (*input)++;
                    u *= 16;

                    if (**input >= L'0' && **input <= L'9') {
                        u += (**input - L'0');
                    } else if (**input >= L'A' && **input <= L'F') {
                        u += (**input - L'A' + 10);
                    } else if (**input >= 'a' && **input <= 'f') {
                        u += (**input - L'a' + 10);
                    } else {
                        return 1;
                    }
                }
                write(u);
            } else {
                sz++;
                if (sz % 10 == 0) output_data = realloc(output_data, sz * 2 + 20);
                output_data[sz-1] = '\\';
                output_data[sz] = **input;
            }
        } else {
            write(**input);
        }

        sz++;
    } loop_end:
    output_data = realloc(output_data, sz * 2 + 2); output_data[sz] = 0;
    output->data = output_data;
    (*input)++;

    return 0;
}

char parseINT (wchar_t** input, JSON* output) {
    double* output_data = malloc(sizeof(double)); *output_data = 0; char sign = 1;

    if (**input == L'-') {
        sign = -1;
        (*input)++;
    }
    if (**input < L'0' || **input > L'9') {free(output_data); return INT_ERROR___NUMBER_NOT_FOUND ;}
    for (; **input >= L'0' && **input <= L'9'; (*input)++) {
        *output_data *= 10;
        *output_data += **input - L'0';
    }

    if (**input == L'.') {
        (*input)++;
        if (**input < L'0' || **input > L'9') {free(output_data); return INT_ERROR___NUMBER_NOT_FOUND_AFTER_POINT;}
        int division = 1;
        for (; **input >= L'0' && **input <= L'9'; (*input)++) {
            division *= 10;
            *output_data += (**input - L'0') / (double) division;
        }
    }

    *output_data *= sign;

    if (**input == L'e' || **input == L'E') {
        (*input)++; unsigned char tens;

        if (**input == L'-') { sign = 1; (*input)++; }
        if (**input < L'0' || **input > L'9') {free(output_data); return INT_ERROR___NUMBER_NOT_FOUND_AFTER_E_CHARACTER;}
        else sign = 0;

        for (; **input >= L'0' && **input <= L'9'; (*input)++) {
            tens *= 10;
            tens += **input - L'0';
        }

        if (sign)
            for (; tens > 0; tens--) {
                *output_data /= 10.0;
            }

        else
            for (; tens > 0; tens--) {
                *output_data *= 10;
            }
    }

    output->type = INT; output->data = output_data;

    return 0;
}

char parseARR (wchar_t** input, JSON* output) {
    JSONArray* output_data = malloc(sizeof(JSONArray));
    output_data->len = 0; output_data->data = malloc(0);

    sleep;
    while (**input != L']') {
        output_data->data = realloc(output_data->data, (++output_data->len) * sizeof(JSON));
        { char a = parseJson(input, output_data->data+output_data->len-1); if (a != 0) return a; }

        sleep;

        if (**input == L']') break;
        else if (**input != L',') { freeJSON(output_data); return 1; }
        (*input)++;
    }
    (*input)++;

    output->type = ARR; output->data = output_data;

    return 0;
}

Ответы (0 шт):