Quais funções _WinMainCRTStartup executa?
-
21-09-2019 - |
Pergunta
Isto faz parte de uma série de pelo menos duas questões intimamente relacionadas, mas distintas.Espero estar fazendo a coisa certa ao perguntar a eles separadamente.
Estou tentando fazer com que meu aplicativo Visual C++ 2008 funcione sem a C Runtime Library.É um aplicativo GUI Win32 sem MFC ou outras coisas sofisticadas, simplesmente API do Windows.
Então eu defino Propriedades do Projeto -> Configuração -> C/C++ -> Avançado -> Omitir Nomes de Bibliotecas Padrão como Sim (sinalizador do compilador /Zl
) e reconstruído.
Então o vinculador reclama de um problema externo não resolvido _WinMainCRTStartup
.É justo, posso dizer ao vinculador para usar um ponto de entrada diferente, digamos MyStartup
.Pelo que reuni na web, _WinMainCRTStartup
faz algumas coisas de inicialização e provavelmente quero MyStartup
para fazer um subconjunto disso.
Então minha pergunta é: Quais funções _WinMainCRTStartup
executar, e qual destes posso omitir se não usar o CRT?
Se você tem conhecimento sobre esse assunto, dê uma olhada em minha outra pergunta também.Obrigado!
Aparte:Por que eu quero fazer isso em primeiro lugar?
- Meu aplicativo não usa explicitamente nenhuma função CRT.
- Eu gosto de aplicativos simples e médios.
- Isso vai me ensinar algo novo.
Solução
O ponto de entrada do CRT faz o seguinte (esta lista não está completa):
- Inicializa o estado global necessário para o CRT. Se isso não for feito, você não pode usar nenhuma função ou estado fornecido pelo CRT.
- Inicializa algum estado global usado pelo compilador. Os cheques de tempo de execução, como o cookie de segurança usado pelo /GS, definitivamente se destaca aqui. Você pode ligar __security_init_cookie você mesmo, no entanto. Pode ser necessário adicionar outro código para outras verificações de tempo de execução.
- Chamadas construtores em objetos C ++. Se você estiver escrevendo código C ++, pode ser necessário imitar isso.
- Recupera a linha de comando e inicia as informações fornecidas pelo sistema operacional e passa sua principal. Por padrão, nenhum parâmetros é passado para o ponto de entrada do programa pelo sistema operacional - todos são provados pelo CRT.
O código -fonte do CRT está disponível no Visual Studio e você pode passar pelo ponto de entrada do CRT em um depurador e descobrir exatamente o que está fazendo.
Outras dicas
A verdadeiro O programa Win32 escrito em C (não C++) não precisa de nenhuma inicialização, então você pode iniciar seu projeto com WinMainCRTStartup() em vez de WinMain(HINSTÂNCIA,...).
Também é possível, mas um pouco mais difícil, escrever programas de console como verdadeiros aplicativos Win32;o nome padrão do ponto de entrada é _mainCRTStartup().
Desative todos os recursos extras de geração de código, como testes de pilha, verificações de array, etc.A depuração ainda é possível.
Inicialização
Às vezes você precisa do primeiro HINSTÂNCIA parâmetro.Para Win32 (exceto Win32s), é corrigido para (HINSTÂNCIA)0x400000.
O nCmdShow parâmetro é sempre SW_SHOWDEFAULT.
Se necessário, recupere a linha de comando com ObterCommandLine().
Terminação
Quando o seu programa gera threads, por ex.ligando GetOpenFileName(), voltando de WinMainCRTStartup() com retornar palavra-chave irá travar seu programa - use SairProcesso() em vez de.
Ressalvas
Você terá problemas consideráveis quando:
- usando quadros de pilha (ou seja,variáveis locais) maiores que 4 KBytes (por função)
- usando aritmética de ponto flutuante (por exemplofloat-> conversão int)
- usando números inteiros de 64 bits em máquinas de 32 bits (operações de multiplicação e mudança de bits)
- usando C++ novo, excluir, e objetos estáticos com construtores diferentes de zero para todos os membros
- usando funções de biblioteca padrão como fopen(), imprimirf() claro
Solucionar problemas
Existe uma biblioteca padrão C disponível em todos os sistemas Windows (desde o Windows 95), a MSVCRT.DLL.
Para usá-lo, importe seus pontos de entrada, por ex.usando meu msvcrt-light.lib (google para isso).Mas ainda existem algumas ressalvas, especialmente ao usar compiladores mais recentes que o MSVC6:
- stack frames ainda estão limitados a 4 KBytes
- _ftol_sse ou _ftol2_sse deve ser encaminhado para _ftol
- _iob_func deve ser encaminhado para _iob
Sua inicialização parece ser executada no momento do carregamento.Pelo menos as funções do arquivo serão executadas aparentemente.
Pergunta antiga, mas as respostas estão incorretas ou concentram-se em um problema específico.
Há uma série de recursos C e C++ que simplesmente não estarão disponíveis no Windows (ou na maioria dos sistemas operacionais, nesse caso) se os programas realmente forem iniciados em main/WinMain.
Veja este exemplo simples:
class my_class
{
public:
my_class() { m_val = 5; }
int my_func(){ return m_val }
private:
int m_val;
}
my_class g_class;
int main(int argc, char **argv)
{
return g_class.my_func();
}
para que este programa funcione conforme esperado, o construtor de my_class deve ser chamado antes de main.Se o programa iniciasse exatamente em main, seria necessário um hack do compilador (nota:O GCC faz isso em alguns casos) para inserir uma chamada de função bem no início de main.Em vez disso, na maioria dos sistemas operacionais e na maioria dos casos, uma função diferente constrói g_class e depois chama main (no Windows, é mainCRTStartup ou WinMainCRTStartup;na maioria dos outros sistemas operacionais com os quais estou acostumado, é uma função chamada _start).
Há outras coisas que C++ e até C precisam ser feitas antes ou depois do trabalho principal.Como stdin e stdout (std::cin e std::cout) podem ser usados assim que main é iniciado?Como funciona o atexit?
O padrão C exige que a biblioteca padrão tenha uma API de sinal semelhante ao POSIX, que no Windows deve ser "instalada" antes de main().
Na maioria dos sistemas operacionais, não há heap fornecido pelo sistema;o tempo de execução C implementa seu próprio heap (o tempo de execução C da Microsoft apenas agrupa as funções Kernel32 Heap).
Até mesmo os argumentos passados para main, argc e argv, devem ser obtidos do sistema de alguma forma.
Você pode dar uma olhada nos artigos (antigos) de Matt Pietrick sobre como implementar seu próprio tempo de execução C para obter detalhes sobre como isso funciona com Windows + MSVC (nota:MinGW e Cygwin implementam coisas específicas de maneira diferente, mas na verdade recorrem ao MSVCRT para a maioria das coisas):http://msdn.microsoft.com/en-us/library/bb985746.aspx