It seems at some point e was corrupted inside _lv_event_mark_deleted probably because of dangling pointers in your code, as said in the last comment.
Global variables are very bad practice, specially when threads are being used. The error in your code, is not anywhere near the place you call lv_obj_clean, check your global variables, possibily you are calling lv_obj_del before removing some timers, events, animations, that use that object. Maybe you are doing something like lv_obj_get_child but using a wrong index, and assuming something would be inside the user_data of that object, but actually is in other object, or the object has already been destroyed⌠Unfortunately, you will need to re-read your whole code.
If your project has been configured properly, LVGL will print logs and assertions at some point. Would seriously recommend using PlatformIO instead of the ArduinoIDE, the advantages are countless.
I donât know if this can help but the crash is happening exactly in this function :
void SearchMyComponents(void* parameters) {
// static int page = 1;
int page = (int)parameters; // Cast back to int
if (page <= 0) {
page = 1;
}
const char* SearchText = lv_textarea_get_text(ui_TextArea1);
String SearchTextString = String(SearchText);
SearchTextString.replace(" ", "+");
http.begin("https://domain.name/PartSense/api/SearchComponents.php?keyword=" + SearchTextString + "&resultperpage=" + MAX_COMPONENTS + "&page=" + page);
http.addHeader("Content-Type", "application/json");
lv_obj_add_flag(ui_No_Result_Container, LV_OBJ_FLAG_HIDDEN);
// size_t freeHeap = ESP.getFreeHeap();
// Serial.println("Free heap before JSON parse: " + String(freeHeap));
// Send HTTP GET request
int httpResponseCode = http.GET();
if (httpResponseCode > 0) {
Serial.println("HTTP Response code: " + String(httpResponseCode));
// Get the JSON response as a string and print it
String responseString = http.getString();
Serial.println("JSON Response: " + responseString);
// Parse JSON response
DynamicJsonDocument jsonResponse(2048); // Adjust size as needed
DeserializationError error = deserializeJson(jsonResponse, responseString);
if (!error) {
// Check if "SearchResults" and "Parts" keys exist
if (jsonResponse.containsKey("SearchResults") && jsonResponse["SearchResults"].containsKey("NumberOfResult") && jsonResponse["SearchResults"].containsKey("Parts")) {
int numberOfResult = jsonResponse["SearchResults"]["NumberOfResult"].as<int>();
JsonArray parts = jsonResponse["SearchResults"]["Parts"].as<JsonArray>();
// Clear previous component data
clearComponentData();
// Create a new screen and switch to it
lv_obj_t* temp_screen = lv_obj_create(NULL);
lv_scr_load(temp_screen);
lv_obj_add_flag(ui_Search_Result, LV_OBJ_FLAG_HIDDEN);
// Clean old search results safely
// lv_event_send(ui_Search_Result, LV_EVENT_DELETE, NULL); // Safely remove any pending events
// lv_obj_invalidate(ui_Search_Result); // Prevent any drawing operations during clean
lv_obj_clean(ui_Search_Result); // Still causes crashes
// lv_obj_del(ui_Search_Result); // Still causes crashes
if (numberOfResult > 0) {
createProductCardsMyComponents(ui_Search_Result, numberOfResult);
createChangePage(ui_Search_Result, numberOfResult, page);
int i = 0;
for (JsonObject part : parts) {
if (i >= MAX_COMPONENTS) break; // Ensure we don't exceed the array size
descriptions[i] = strdup(part["description"] | "");
if (!descriptions[i]) {
Serial.println("Memory allocation failed for descriptions[" + String(i) + "]");
continue;
}
manufacturers[i] = strdup(part["manufacturer"] | "");
if (!manufacturers[i]) {
Serial.println("Memory allocation failed for manufacturers[" + String(i) + "]");
free((void*)descriptions[i]);
descriptions[i] = nullptr;
continue;
}
partNumbers[i] = strdup(part["part_number"] | "");
if (!partNumbers[i]) {
Serial.println("Memory allocation failed for partNumbers[" + String(i) + "]");
free((void*)descriptions[i]);
descriptions[i] = nullptr;
free((void*)manufacturers[i]);
manufacturers[i] = nullptr;
continue;
}
manufacturerPartNumbers[i] = strdup(part["mpn"] | "");
if (!manufacturerPartNumbers[i]) {
Serial.println("Memory allocation failed for manufacturerPartNumbers[" + String(i) + "]");
free((void*)descriptions[i]);
descriptions[i] = nullptr;
free((void*)manufacturers[i]);
manufacturers[i] = nullptr;
free((void*)partNumbers[i]);
partNumbers[i] = nullptr;
continue;
}
// Print extracted data
Serial.println("Component " + String(i + 1) + ":");
Serial.println("Description: " + String(descriptions[i]));
Serial.println("Manufacturer: " + String(manufacturers[i]));
Serial.println("Manufacturer Part Number: " + String(manufacturerPartNumbers[i]));
lv_label_set_text(productCardComponents[i].Mfr_Part, manufacturerPartNumbers[i]);
lv_label_set_text(productCardComponents[i].Description, descriptions[i]);
lv_label_set_text(productCardComponents[i].Manufacturer, manufacturers[i]);
lv_label_set_text(productCardComponents[i].Part_Number, partNumbers[i]);
productCardComponents[i].part_number_const = partNumbers[i];
const char* partNumberText = lv_label_get_text(productCardComponents[i].Part_Number);
String response = "https://theyoungmaker.dev/PartSense/images/" + String(partNumberText) + "/96x96.bmp";
if (imagesEnabled) {
if (getImageFromURL(response, i)) {
Serial.println("Image downloaded and processed successfully");
lv_img_set_src(productCardComponents[i].Image, &productImages[i]);
} else {
Serial.println("Failed to download or process image");
}
}
i++;
}
} else {
lv_obj_clear_flag(ui_No_Result_Container, LV_OBJ_FLAG_HIDDEN);
}
} else {
Serial.println("JSON response does not contain expected keys");
}
lv_obj_add_flag(ui_Spinner1, LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_flag(ui_Search_Result, LV_OBJ_FLAG_HIDDEN);
// Switch back to the original product screen
lv_scr_load(ui_Component_Search);
} else {
Serial.println("Failed to parse JSON: " + String(error.c_str()));
}
} else {
Serial.println("Error on HTTP request: " + http.errorToString(httpResponseCode));
}
http.end();
vTaskDelete(SearchMyComponentsTaskHandle);
}