Définir un point d'entrée

Résolu
cs_Havy Messages postés 7 Date d'inscription dimanche 12 juillet 2009 Statut Membre Dernière intervention 12 août 2009 - 12 juil. 2009 à 15:22
cs_Havy Messages postés 7 Date d'inscription dimanche 12 juillet 2009 Statut Membre Dernière intervention 12 août 2009 - 20 juil. 2009 à 19:39
Bonjour, sachant que tout programme console doit contenir la fonction main pour fonctionner, car c'est le point d'entrée, je voudrais savoir s'il est possible de définir son propre point d'entrée.

Par exemple je voudrais faire ceci :

#include

using namespace std;

void Test()
{
}

Et donc, faire en sorte que quand je compile, il n'y'a pas référence à main mais à Test comme fonction principale pour faire démarrer le programme.

J'ai fais des recherches concernant la directive #pragma et entry, mais je n'ai rien trouvé qui pourrait m'aider.

NB : J'utilise Dev-C++ si cela peut aider :)

Merci d'avance pour votre aide, passez une bonne journée et bonne prog ;)

3 réponses

cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
18 juil. 2009 à 22:52
Salut,

Alors en fait, dans un fichier .exe, il y a un point d'entrée "entry point". C'est une adresse définie dans le header du fichier exécutable, au milieu d'autres infos :

OPTIONAL HEADER VALUES
     10B magic #
    8.00 linker version
   12E00 size of code
   18800 size of initialized data
       0 size of uninitialized data
   126FE address of entry point
    1000 base of code


Quand on demande à Windows d'exécuter un programme, il charge en mémoire le contenu du .exe, en mappant les sections de celui-ci à divers emplacement, en se basant sur les infos dans le header. Puis il charge les dll nécessaires (Précisées dans une table elle aussi accessible via le header), et résous les adresses des fonctions importées. Il appelle aussi les point d'entrée de ces dlls.

Et finalement, le programme démarre "réellement" quand le point d'entrée du .exe est appelé.

Mais quel code ce trouve ici ? Le code du main compilé ? NON !
Il y a le code d'initialisation de la runtime, qu'elle soit C ou C++.

En effet, pour pouvoir fonctionner, la CRT a besoin d'une phase d'initialisation, et d'une phase de libération, avant et après le main. C'est là que va d'ailleurs se faire la préparation de argv et argc, qui ne sont pas passé en argument du vrai point d'entrée (Il n'a pas d'arguments pour un .exe).

La CRT est une librairie comme une autre (Dans le cas de gcc, il s'agit de la glibc), qui fournit toutes les fonctions de base du standard C (printf, fopen, system, malloc, strcat...), sauf qu'elle est dans le chemin du lieur par défaut (-lC par défaut quoi). Pour le C++, le principe doit être similaire. Le C++ est forcé d'exécuter du code caché lui aussi, en plus de celui du C (Des exécution de constructeurs notamment).

Mais la particularité de cette librairie, donc, c'est qu'elle appelle le main. Au vrai point d'entrée du .exe, ont trouve quelques chose comme ça (C'est pas du tout comme ça mais c'est l'esprit, dans le cas d'une appli console) :

/* Déclaration du main */
int main(int argc, char** argv);

int __cdecl WinMainCRTStartup()
{
  int nResult;
  InitCrt();
  nResult = main(GetArgC(), GetArgV());
  FreeCrt();
  return nResult;
}


Comment le linker sait-il quelle adresse mettre comme entry point dans le header ? Il met l'adresse de WinMainCRTStartup (Appli gui) ou de mainCRTStartup (Appli console). C'est codé en dur dans le linker ! La CRT définie ces deux symboles donc quoiqu'il arrive, ils sont trouvés au link.

Par contre quand on oublie de définir un main, pouf, le linker n'est pas content, car il ne trouve pas l'implémentation de la fonction main appelée par le code d'initialisation de la CRT (WinMain dans le cas d'une appli GUI).

Première constatation... Si on veut définir son propre point d'entrée, la CRT n'est pas initialisée ! Bilan, définir son propre point d'entrée, s'est aller au devant de très gros ennui si on utilise des fonctions standard... Par contre, avec windows.h par exemple, pas de soucis !

Bon, donc supposons que l'on décide de ne pas utiliser la lib standard...

Il faut donc, par exemple pour une appli GUI, se débarrasser de la CRT en entrée du lieur, et définir WinMainCRTStartup (Méthode qui marche pour VC et gcc donc plus portable que le /entry). Exemple de code :
#include "windows.h"

int __cdecl WinMainCRTStartup()
{
  MessageBox(NULL, "Je n'ai pas de CRT", "Point d'entrée custom", MB_OK);
  return 0;
}


Ce code n'inclus que windows.h, donc on ne touche pas à la CRT.

Pour compiler, on demande à gcc de ne pas utiliser les libs par défaut :
-nostartfiles -nodefaultlibs -nostdlib pour gcc
/NODEFAULTLIB pour VC

Par contre faut ajouter manuellement d'éventuelles librairies par défaut manquante du coup (Ici, MessageBox est dans user32) ->
gcc -Wall -ansi -pedantic test.c -o test.exe -nostartfiles -nodefaultlibs -nostdlib -luser32

Et nous voilà avec un superbe .exe de 5ko, sans initialisation et libérations inutile... Bref une bête de course très propre.
1
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
12 juil. 2009 à 17:22
oui.

Sous Visual C++ Express (mais je pense que ça t'aidera pas)

#pragma comment(linker,"/entry:Test")


du moins, tu sais que c'est possible maintenant.
0
cs_Havy Messages postés 7 Date d'inscription dimanche 12 juillet 2009 Statut Membre Dernière intervention 12 août 2009
20 juil. 2009 à 19:39
Je vous remercie beaucoup pour toutes ces infos, je vais travailler sur tout ça :)

Encore merci et passez une bonne journée ;)
0
Rejoignez-nous