| 2562 | } |
| 2563 | |
| 2564 | void ObjectDB::cleanup() { |
| 2565 | mutex.lock(); |
| 2566 | |
| 2567 | if (slot_count > 0) { |
| 2568 | WARN_PRINT("ObjectDB instances leaked at exit (run with --verbose for details)."); |
| 2569 | if (OS::get_singleton()->is_stdout_verbose()) { |
| 2570 | // Ensure calling the native classes because if a leaked instance has a script |
| 2571 | // that overrides any of those methods, it'd not be OK to call them at this point, |
| 2572 | // now the scripting languages have already been terminated. |
| 2573 | MethodBind *node_get_path = ClassDB::get_method("Node", "get_path"); |
| 2574 | MethodBind *resource_get_path = ClassDB::get_method("Resource", "get_path"); |
| 2575 | Callable::CallError call_error; |
| 2576 | |
| 2577 | for (uint32_t i = 1; i < block_count; i++) { |
| 2578 | for (uint32_t j = 0; j < blocks_max_sizes[i]; j++) { |
| 2579 | if (blocks[i][j].validator) { |
| 2580 | Object *obj = blocks[i][j].object; |
| 2581 | |
| 2582 | String extra_info; |
| 2583 | if (obj->is_class("Node")) { |
| 2584 | extra_info = " - Node path: " + String(node_get_path->call(obj, nullptr, 0, call_error)); |
| 2585 | } |
| 2586 | if (obj->is_class("Resource")) { |
| 2587 | extra_info = " - Resource path: " + String(resource_get_path->call(obj, nullptr, 0, call_error)); |
| 2588 | } |
| 2589 | |
| 2590 | uint64_t id = uint64_t(i) | (uint64_t(blocks[i][j].validator) << OBJECTDB_SLOT_MAX_COUNT_BITS) | (blocks[i][j].is_ref_counted ? OBJECTDB_REFERENCE_BIT : 0); |
| 2591 | DEV_ASSERT(id == (uint64_t)obj->get_instance_id()); // We could just use the id from the object, but this check may help catching memory corruption catastrophes. |
| 2592 | print_line("Leaked instance: " + String(obj->get_class()) + ":" + uitos(id) + extra_info); |
| 2593 | } |
| 2594 | } |
| 2595 | } |
| 2596 | print_line("Hint: Leaked instances typically happen when nodes are removed from the scene tree (with `remove_child()`) but not freed (with `free()` or `queue_free()`)."); |
| 2597 | } |
| 2598 | } |
| 2599 | |
| 2600 | for (uint32_t i = 1; i < block_count; i++) { |
| 2601 | memfree(blocks[i]); |
| 2602 | } |
| 2603 | mutex.unlock(); |
| 2604 | } |
| 2605 | Object *ObjectDB::get_instance(ObjectID p_instance_id) { |
| 2606 | uint64_t id = p_instance_id; |
| 2607 | NextFree slot; |
nothing calls this directly
no test coverage detected