Ошибка при удалении памяти 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;
}