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?

  1. Meu aplicativo não usa explicitamente nenhuma função CRT.
  2. Eu gosto de aplicativos simples e médios.
  3. Isso vai me ensinar algo novo.
Foi útil?

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top