Há um requisito no projeto para usar std::queue para processar eventos de mensagens sequencialmente.
Um exemplo simples é o seguinte:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
No caso de teste, empurrei objetos na fila my_event_queue três vezes no total e, em seguida, usei loops while e front para obter o endereço do objeto na fila e colocá-lo.
O problema está em excluir my_event. Em teoria, std::queue não é responsável pela destruição de objetos. Ou seja, seu novo objeto precisa ser excluído por si só, então eu o excluo toda vez que retiro um objeto.
Então o aborto ocorreu quando o loop while atingiu a segunda vez.Quando olhei para a memória, descobri que a memória durante a segunda exclusão não estava alocada, então o aborto foi acionado.
Como pode ser visto na captura de tela, o tamanho do identificador é de 4 bytes, o que significa que a área de memória está alocada na área marcada por três caixas vermelhas. De acordo com a suposição, cada exclusão deve apagar a área de memória de 4 bytes. Ou seja, apague o primeiro quadro vermelho pela primeira vez e apague o segundo quadro vermelho pela segunda vez.
Mas, na verdade, a primeira exclusão apagou 20 bytes do comprimento da memória, o que resultou na segunda exclusão acessando a memória não alocada.
Pesquisas subsequentes descobriram que isso ocorreu porque um valor foi passado em vez de um ponteiro ao empurrar, fazendo com que std::queue chamasse o construtor de cópia (se o construtor de cópia não for definido explicitamente, o padrão será chamado), então a fila é na verdade, uma cópia salva.
A cópia será ativamente destruída toda vez que aparecermos, e a ontologia não será afetada (precisamos excluí-la manualmente), então apenas pegamos o ponteiro da cópia e a excluímos após o pop. O endereço neste momento já está um ponteiro pendente. O comportamento é indefinido
Observe que 20 bytes é o tamanho padrão da fila
Como resolver isso?
Podemos declarar um array com antecedência, colocar o endereço após new nele e excluí-lo em sequência após o último uso.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
当然更好的办法是使用智能指针来保证自动释放内存 std::queue<std::unique_ptr<MyEvent>> my_event_queue;
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
|