Crash On flecs_defer_end
Esp9527 opened this issue · comments
Describe the bug
flecs 3.2.9
To Reproduce
Crash On flecs source code ( event is EcsCmdEvent )
`
bool flecs_defer_end(
ecs_world_t *world,
ecs_stage_t *stage)
{
// event is EcsCmdEvent
if (cmd->is._1.value) {
// Crash Here
flecs_stack_free(cmd->is._1.value, cmd->is._1.size);
}
}
`
Because flecs_cmd_new don't set cmd->is._1.size (0 or 1) in flecs_enqueue?
`
Here is code
void flecs_enqueue(
ecs_world_t *world,
ecs_stage_t *stage,
ecs_event_desc_t *desc)
{
ecs_cmd_t *cmd = flecs_cmd_new(stage);
cmd->kind = EcsCmdEvent;
cmd->entity = desc->entity;
ecs_stack_t *stack = &stage->cmd->stack;
ecs_event_desc_t *desc_cmd = flecs_stack_alloc_t(stack, ecs_event_desc_t);
ecs_os_memcpy_t(desc_cmd, desc, ecs_event_desc_t);
if (desc->ids && desc->ids->count != 0) {
ecs_type_t *type_cmd = flecs_stack_alloc_t(stack, ecs_type_t);
int32_t id_count = desc->ids->count;
type_cmd->count = id_count;
type_cmd->array = flecs_stack_alloc_n(stack, ecs_id_t, id_count);
ecs_os_memcpy_n(type_cmd->array, desc->ids->array, ecs_id_t, id_count);
desc_cmd->ids = type_cmd;
} else {
desc_cmd->ids = NULL;
}
cmd->is._1.value = desc_cmd;
if (desc->param || desc->const_param) {
ecs_assert(!(desc->const_param && desc->param), ECS_INVALID_PARAMETER,
"cannot set param and const_param at the same time");
const ecs_type_info_t *ti = ecs_get_type_info(world, desc->event);
ecs_assert(ti != NULL, ECS_INVALID_PARAMETER,
"can only enqueue events with data for events that are components");
void *param_cmd = flecs_stack_alloc(stack, ti->size, ti->alignment);
ecs_assert(param_cmd != NULL, ECS_INTERNAL_ERROR, NULL);
if (desc->param) {
if (ti->hooks.move_ctor) {
ti->hooks.move_ctor(param_cmd, desc->param, 1, ti);
} else {
ecs_os_memcpy(param_cmd, desc->param, ti->size);
}
} else {
if (ti->hooks.copy_ctor) {
ti->hooks.copy_ctor(param_cmd, desc->const_param, 1, ti);
} else {
ecs_os_memcpy(param_cmd, desc->const_param, ti->size);
}
}
desc_cmd->param = param_cmd;
desc_cmd->const_param = NULL;
}
}
`
Expected behavior
A clear and concise description of what you expected to happen.
Additional context
I'm not very familiar with the underlying mechanism, is Here missing initialization?
`
static
ecs_cmd_t* flecs_cmd_new(
ecs_stage_t *stage)
{
ecs_cmd_t *cmd = ecs_vec_append_t(&stage->allocator, &stage->cmd->queue,
ecs_cmd_t);
cmd->is._1.value = NULL;
cmd->next_for_entity = 0;
cmd->entry = NULL;
// add set zero here ?
cmd->id = 0;
cmd->is._1.size = 0;
return cmd;
}
`
Can you provide a reproducer for this issue?
Both size
and value
should be initialized (size to 0 by flecs_cmd_new
, value by flecs_enqueue
), so I think something else might be causing this. I also tried to initialize the result of ecs_vec_append_t
with random data, which also didn't reproduce the issue.
Yesterday's description of the crash was not very clear
`
void flecs_stack_free(
void *ptr,
ecs_size_t size)
{
// crash when cmd->is._1.size > ECS_STACK_PAGE_SIZE
if (size > ECS_STACK_PAGE_SIZE) {
// but ptr is stack ptr when EcsCmdEvent
ecs_os_free(ptr);
}
}
`
I'll try to reproduce this problem
Here are code will crash on my pc (Win11), flecs v3.2.9
`
#include <flecs.h>
#include <iostream>
static const uint64_t PLAYER_SIZE = 8888;
static const uint64_t EFFECT_SIZE = 10;
static const uint64_t PLAYER_COUNT = 20;
static const uint64_t EFFECT_COUNT = 20;
struct Player{
char data[PLAYER_SIZE] = {};
};
struct Effect {
char data[EFFECT_SIZE] = {};
};
int main() {
flecs::world world;
world.component<Player>();
world.component<Effect>();
world.system<Player>()
.each([](flecs::entity p, Player){
Effect effect = {};
for(int i = 0; i< EFFECT_COUNT;++i) {
p.world().event<Effect>()
.ctx(effect)
.id<Player>()
.entity(p)
.enqueue();
}
});
world.observer<>()
.event<Effect>()
.term<Player>()
.each([](flecs::entity){
std::cout << "do effect" << std::endl;
});
world.defer_begin();
for(int i = 0; i< PLAYER_COUNT; ++i) {
auto player = world.entity();
player.set<Player>({});
}
world.defer_end();
// ecs_log_set_level(3);
world.app().target_fps(20).run();
return 0;
}
`
ps : if change PLAYER_COUNT = 1, EFFECT_COUNT =1, will crash on malloc function or free function (in random). maybe same reason cause whem memry is bad
That reproduced! Thanks :)
Fixed!