Só recapitulando:
O erro estava em API Windows, gerando erros aleatórios.
Em outras palavras, erros em GUI, coisa que a maioria aqui usa.
GUI mistura funcionamento DO WINDOWS com funcionamento do aplicativo.
Parte do aplicativo pode ficar preso na janela Windows, em execução ou não.
Dependendo do erro, PODE, não que aconteça, mas PODE ficar parte do aplicativo funcionando enquanto outra parte foi encerrada.
ISSO NÃO TEM A VER COM USAR MULTITHREAD NO APLICATIVO, GUI por si só já tem um comportamento desse jeito.
Uma coisa semelhante que aconteceu com outro usuário:
Ele criou uma DIALOG com Timer pra fechar sozinha.
Só que essa dialog chamava outra DIALOG.
O timer acabou encerrando as rotinas da primeira dialog depois de um certo tempo, destruindo variáveis e outras coisas.
Acabou gerando um erro na dialog aberta, parecendo sem explicação.
Situação:
Janela de DIALOG é controlada pelo Windows, aguarda uma mensagem pra fechar.
Quando abre DIALOG MODAL, a janela anterior fica "suspensa", não recebe mensagens.
O timer encerrou a rotina, enviou mensagem pra dialog fechar, mas a dialog continuou na tela, afinal, não recebe mensagens.
Apenas olhando a tela, não se vê erro nenhum.
Só quando precisou de alguma coisa dessa dialog é que o erro apareceu.
Não era erro na rotina, mas mostrava como sendo na rotina, pela falta de alguma variável que foi-se embora.
Podemos considerar erro do programador, mas..... o erro foi dele ou da LIB que não previu isso?
GUI/API Windows é coisa complicada, liberar recursos pra programador pode gerar situações não previstas.
Com o tempo e com o uso, com programadores detectando problemas e solicitando correções, a LIB vai ficando mais "redonda" e evitando problemas.
Acabei chegando nesta página, do WM_CLOSE
https://learn.microsoft.com/pt-br/windo ... g/wm-close
Note que interessante a rotina de processar eventos:
Código: Selecionar todos
LRESULT CALLBACK WindowProc(
__in HWND hWindow,
__in UINT uMsg,
__in WPARAM wParam,
__in LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
DestroyWindow(hWindow);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWindow, uMsg, wParam, lParam);
}
return 0;
}
É rotina em C, tudo bem, mas dá uma boa idéia do que acontece.
Note que tem o equivalente a OTHERWISE, o que fazer no caso de não ser mensagem prevista.
É algo como: não resolvi, resolve você, mas com outra chamada de função.
Por isso, NO MEU CASO, acho que aconteceu muita recursividade, porque ficou nessa de tentar achar alguém que resolvesse, chamando rotinas e mais rotinas.
Tava invertido, então estava resolvido, mas mesmo assim tentando achar alguém pra resolver, provavelmente recebendo a mensagem, repassando, recebendo, repassando, até que em algum momento o limite de recursividade chegava ao fim.
Mesmo assim, pode acontecer com qualquer LIB, pra situações não previstas.
Outro exemplo, colocar um controle que vai na DIALOG dentro de outro controle, de um TAB.
Tem coisas que o controle resolve, tem coisas que é a DIALOG (o "pai" dele").
Mas e quando está no TAB? TAB passou a ser o "pai" do controle.
Pode ser que esse tab precise fazer tudo que a dialog fazia e a LIB vai colocando só conforme vai precisando/acontecendo.
E isso poderia causar a mesma situação que aconteceu comigo.
Não é técnico, não sei se isso se aplica ao TAB que usei de exemplo, mas, é normal a gente ir fazendo cada vez mais uso de recursos da LIB, que podem não ter sido previstos.
Igual eu fiz, parecia estar tudo funcionando normalmente, mas internamente estava tudo errado.
E o que mais complicou, é que não dava erro todo dia, podia demorar 1 semana.
Isso me fez pensar:
Se com tudo errado demorava uma semana pra dar erro...
Se estiver só um pouco errado.... sei lá quanto tempo pode demorar...
Talvez só um programador específico, numa situação específica, num uso específico, é que o erro apareça mais vezes.