OVH Cloud OVH Cloud

Start_up code

26 réponses
Avatar
Pierre Maurette
Bonjour,
Je recherche un exemple d'implémentation qui, conformément à ce que semble
autoriser la norme, ne définirait aucune fonction main (ou WinMain, ou
autre).
J'imagine qu'une telle implémentation génèrerait un code de prologue qui
lancerait les constructeurs d'une ou plusieurs classes, dont une nommée par
exemple Application.
Si j'ai bien compris, C++Builder6 pourrait fournir cet exemple, s'il
"cachait", ou plutôt ne créait pas, et donc rendait non-éditable le fichier
NomDuProjet.cpp (macro d'instanciation de la fiche principale du projet +
WinMain()).
De toutes façons, il faut bien que, sous Windows, le lieur fournisse en fin
de compte un point d'entrée conforme au prototype WinMain() ....
Ce n'est pas pour un devoir (j'ai un peu passé l'âge), mais c'est quand même
pour un travail de rédactiion.
Bonne messe, Cordialement,
Pierre

10 réponses

1 2 3
Avatar
kanze
Loïc Joly wrote in message
news:<bqvlkm$vdr$...
Pierre Maurette wrote:
1 A program shall contain a global function called main, which is
the designated start of the program. It is implementation-defined
whether a program in a freestanding environment is required to
define a main function.


Nous avons donc les mêmes sources ... C'est l'anglais qui me
perturbe. Plus précisément, le "shall contain".


Et elles sont assez fiable en ce qui concerne le C++ tel que défini
dans la norme ;)

Je comprend le "shall contain" ainsi : Un programme en C++ "hosted"
(la grosse majorité) DOIT avoir une fonction main, mais un programme
"freestanding" peut en avoir une ou non, comme ça l'arrange.


Oui et non. D'abord, il y a bien une contradiction dans les deux phrases
de la norme -- quand la norme dit que « A program shall contain a global
function called main [...] », ça veut dire que s'il ne le contient pas,
le programme est erroné (et je crois qu'un diagnostique est exigé). La
phrase qui suit, en revanche, dit que c'est défini par l'implémentation
dans certains cas. Si l'intention est quand même évident, je crois qu'il
aurait été mieux si le paragraphe avait commencé « A hosted program
shall contain a global function called main [...] ».

Note qu'une implémentation « freestanding » peut fournir tout ce qu'elle
veut en plus de la minimum exigé. Et que certaines implémentations très
répandues (VC++, g++, Comeau...) sont en fait des implémentations
« freestanding ».

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16



Avatar
kanze
"Pierre Maurette" <mmaauurreettttttee.ppiieerrrree@@ffrreeee.ffrr> wrote
in message news:<3fd34d90$0$29079$...
"Thomas Abbé" a écrit

bon, je ne sais pas si je te reponds a ta question. si tu programmes
en c++, il faut avoir une fonction main. selon le C++ standard, elle
doit etre de la forme int main() ou int main(int argc, const char*
argv[]) selon le C standard, aussi dautres variantes comme void
main() sont possible, mais ce nest pas recommende. ca depend en plus
du compilateur.



En fait, « void main » n'a jamais été légal, que ce soit en C ou en C++.

Non, je ne pense pas que ça dépende du compilateur.


Disons qu'à la fin, tout dépend du compilateur:-). Les normes C et C++
sont à peu près identiques en ce qui concerne la nécessité et la forme
de main :

- Elles ne spécifient que ce qui concerne les environement « hosted ».
Pour des processeurs embarqués, etc., c'est à l'implémentation de
définir ce qu'elle veut.

- La fonction main doit avoir un type de retour « int ». Toujours. En
C++, un autre type de retour exige un message d'erreur du
compilateur.

- Une implémentation peut accepter plusieurs variantes en ce qui
concerne les paramètres. Elle est obligée à supporter au moins deux :
int main( void )
int main( int, char** )
Elle peut en supporter d'autres.

En C++, les multiples possibilités ne représentent pas un surcharge.
Il n'y a jamais qu'une seule fonction main, qui ne peut pas être
surchargée ; malgré les différentes possibilités de le définir,
c'est toujours la même fonction.

En C++, il y a en plus des restrictions supplémentaires en ce qui
concerne main :

- Comme je viens de dire, elle ne peut pas être surchargée.

- On ne peut pas en prendre son adresse. (Il y a plusieurs raisons
pour ceci, mais la plus évidente est simple : quel serait le type
d'une fonction qu'on peut déclarer indifféremment avec ou sans
paramètres.)

- On ne peut pas l'appeler.

En C++, donc (à l'encontre de C), main est une fonction vraiment
spéciale.

Prenez un programme qui tourne, modifiez votre :
int main(int argc, const char* argv[])
en
int pied(int argc, const char* argv[])
Le compilateur s'en tamponne (testé sous Borland et G++).


Oui est non. Tu as bien le droit de définir une fonction qui s'appelle
pied. Tu as également droit à donner à cette fonction la signature que
tu veux. Mais ça n'a rien à voir. Prenons par exemple :

int pied()
{
return 0 ;
}

int pied( int, char** )
{
return 1 ;
}

Pas de problème. Maintenant, changer le nom en main, et voir ce qui se
passe.

Tu peux aussi écrire des choses du genre :

int (*pf)( int, char** ) = &pied ;

ou

int i = pied() ;

Là aussi, remplacer pied par main, et le compilateur râle.

Tu peux aussi écrire :

void pied() {}

Un compilateur C++ conforme émettra un message d'erreur si tu remplaces
pied par main.

Ça marche également avec orteil(), jambe(), etc. Le compilateur génère
du code objet pour les fonctions que vous lui proposez.


Sauf main. Typiquement (au moins historiquement), le compilateur émet du
code généré différent si le nom de la fonction est « main ».

C'est le lieur qui ne veut pas de votre pied. Ou plutôt, si, il prend
votre pied, mais il lie votre code avec du code de start-up (qui varie
selon la cible spécifiée). Ce code fait le tampon entre votre code et
le chargeur de l'OS.


C'est une implémentation fréquente. Ce n'est pas exigée par la norme.

En fait, historiquement, beaucoup de compilateurs C++ généraient la
fonction main comme si c'était « extern "C" », et se servait du ctr0 du
C. Et dans ta fonction main, ils ajoutaient des appels à du code de
démarrage et d'arrêt propre à C++ : construction et destruction des
variables static, particulièrement. (C'est une des raisons, d'ailleurs,
pourquoi l'appel récursif de main est interdit.)

Si vous avez demandé une appli console, le code de start-up veut un
main() et vous avez des chances d'être portable.

Si vous construisez une appli Windows, il lui faudra un WinMain.


Et donc, ce n'est pas un programme C++ hosted.

Une DLL, un DLLEntryPoint (et un DLLMain ).


Le C++ n'admet pas l'édition de liens dynamiques, même si la plupart des
implémentations le supportent. Et dans les implémentations qui le
supportent (mais j'avoue m'y connaître surtout sous Posix ici) je n'ai
jamais vu où il fallait un point d'entrée particulière.

Entrer directement sur une instance de classe principale me parait
possible (dans le futur ?). Ce que je souhaitais, c'était savoir s'il
existait un exemple.


C'est ce que fait Java, plus ou moins. Je n'en vois pas l'intérêt. La
norme C++ l'intérdit.

Une autre possibilité, peut-être plus intéressante, c'est celui des
langages du type Modula. Chaque module peut avoir un « main » (qui ne se
déclare pas comme une fonction) ; l'éditeur de liens fait un tri
topologique sur les dépendances des modules, et appelle les « main »
dans l'ordre qu'il faut. En principe, ça serait une belle solution au
problème de l'ordre d'initialisation en C++. Dans la pratique, l'absence
d'un concepte clair de module le rendrait peu clair, et des possibilités
telles que l'initialisation statique des pointeurs font que déterminer
les dépendences n'est pas pratiquement possible.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16


Avatar
kanze
"Pierre Maurette" <mmaauurreettttttee.ppiieerrrree@@ffrreeee.ffrr> wrote
in message news:<3fd382ff$0$7133$...

Revenons à nos moutons : en C et encore plus en C++, le main() devrait
également être tout petit.


LE main, oui. Rien ne t'empêche de définir une fonction qui s'appelle
Main. N'oublions pas qu'en C et en C++, le compilateur distingue entre
les majuscules et les minuscules. (En C90, en revanche, l'éditeur de
liens n'en est pas obligé, et en plus, il peut ne prendre en compte que
les six premiers caractères.)

Un programme 100% portable ne tournera que sur des machine/OS dotés
d'un mode console, dont le format d'exécutable permettra au lieur de
faire en sorte (code de prologue ou de startup) que le main() reçoive
correctement formatés les paramètres saisis par l'utilisateur. C'est
le cas de DOS puis de tous les Windows.


Je ne suis pas sûr de ce que tu entends par « mode console ». Je n'ai
jamais eu des « modes » dans mes programmes -- ils font ce qu'ils font.
La plupart de MES programmes ne connaissent pas de console système, ni
de console utilisateur en général, mais c'est un caractèristique de ce
que j'écris et de ce que je veux que le programme fasse. (Je travaille
surtout sur des serveurs, qui sont lancer avec cin, cout et cerr
connectés à /dev/null.)

En revanche, console ou non, tous mes programmes ont un « main », et
reçoivent des paramètres de la ligne de commande. Souvent, ils
n'acceptent qu'un seul paramètre, qui est le nom d'un fichier de
commande, mais celui-là, au moin, y est.

Mais j'ai l'impression que cette portabilité à 100%(du source de
l'application entière) est moins importante que le fait de bien
séparer ce qui est spécifique de ce qui est portable, le coeur de
métier du programme, ses classes ou fonctions.


Tout à fait.

Il est clair que la portabilité de certains utilitaires n'a pas de
sens. Si le travail sur l'interface est important, il faudra se
tourner vers des solutions comme wxWindows. Ça semble séduisant, je
suis en train de le regarder sous Wondows, je verrai ensuite sous
Linux. Il est certain que sur d'autres bécannes que des micros, la
portabilité totale est plus intéressante.


La portabilité totale, aujourd'hui, est un leurre. Au moins pour une
application. J'écris bien des petits outils de développement que je
crois portable, mais c'est difficile à concevoir une application
aujourd'hui qui n'accède pas à des sockets et n'a pas de threads. (Un
compilateur, peut-être ?)

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

Avatar
Loïc Joly
DINH Viêt Hoà wrote:



En d'autres termes, WinMain n'est pas un "specific" de mon compilo.
C'est juste ce dernier point que je voulais vérifier.



main() est également considéré comme une fonction ordinaire.


Pas vraiment. Par exemple, on n'a pas le droit d'appeller main depuis
son programme.

--
Loïc


Avatar
espie
In article ,
wrote:
Note qu'une implémentation « freestanding » peut fournir tout ce qu'elle
veut en plus de la minimum exigé. Et que certaines implémentations très
répandues (VC++, g++, Comeau...) sont en fait des implémentations
« freestanding ».


Depuis quelques temps, g++ propose un drapeau -fhosted/-ffree-standing
qui, en plus des multiples -std=, est cense te permettre de choisir le
type d'implementation que tu veux. Meme si, bien sur, de par sa nature,
g++ est un peu dependant de l'OS sous-jacent pour en faire un compilo
conforme, je suis sur que Gaby et d'autres se feront un plaisir, tot ou
tard, de corriger ce petit point de detail quant a la definition de main,
si necessaire.

Mais bon, de toutes facons, une implementation conforme, c'est une
implementation qui permet de compiler des unites de programme de maniere
conforme a la norme, non ? g++ aurait parfaitement le droit de cacher
la partie strictement conforme derriere -fonce-in-a-blue-moon, n'est-ce-pas ?

Avatar
DINH Viêt Hoà

Depuis quelques temps, g++ propose un drapeau -fhosted/-ffree-standing
qui, en plus des multiples -std=, est cense te permettre de choisir le
type d'implementation que tu veux.


d'ailleurs, j'ai peut-être une question un peu hors sujet mais si l'on
veut faire un code freestanding (par exemple un OS) en C++ (ce n'est pas
mon cas, rassurez-vous) avec g++. Quelles fonctions faut-il définir ?
Enfin ce que je veux demander plus précisément, c'est : quelle fonctions
C ou C++ sont supposées existantes dans la bibliothèque standard et que
g++ utilise pour implémenter les choses spécifiques au C++ (new, new[],
delete, delete[], d'autres ... ?).

Des gens connaissent-ils le prototype de ces fonctions ?

--
DINH V. Hoa,

etPan! - newsreader, mail user agent -- http://libetpan.sf.net/etpan

Avatar
kanze
(Marc Espie) wrote in message
news:<br4bpu$1mge$...
In article ,
wrote:
Note qu'une implémentation « freestanding » peut fournir tout ce
qu'elle veut en plus de la minimum exigé. Et que certaines
implémentations très répandues (VC++, g++, Comeau...) sont en fait
des implémentations « freestanding ».


Depuis quelques temps, g++ propose un drapeau -fhosted/-ffree-standing
qui, en plus des multiples -std=, est cense te permettre de choisir le
type d'implementation que tu veux. Meme si, bien sur, de par sa
nature, g++ est un peu dependant de l'OS sous-jacent pour en faire un
compilo conforme, je suis sur que Gaby et d'autres se feront un
plaisir, tot ou tard, de corriger ce petit point de detail quant a la
definition de main, si necessaire.

Mais bon, de toutes facons, une implementation conforme, c'est une
implementation qui permet de compiler des unites de programme de
maniere conforme a la norme, non ? g++ aurait parfaitement le droit
de cacher la partie strictement conforme derriere
-fonce-in-a-blue-moon, n'est-ce-pas ?


Pourquoi faire. Je suis très content avec g++ comme il est. Ma remarque
était juste pour rélativiser ce que dit la norme -- la norme dit aussi
que void main est interdit, et exige un message d'erreur, mais nous
savons tous que tous les compilateurs ne sont pas conformes sur ce
point:-).

Quant à la question initiale de s'il fallait un main ou non, la réponse
dépend malheureusement du compilateur, et de ce qu'on en fait avec le
compilateur. Personnellement, je trouve que dans ce cas-là, il n'y a pas
de véritable jusitification, mais le fait est que si tu veux écrire un
programme avec un GUI sous Windows, ton programme n'aurait pas de
fonctionne main. C'est dommage, mais insister que c'est le compilateur
qui a tort ne va pas avance ton programme.

Quant à g++, je ne sais pas quelle est la position actuelle des
développeurs sur ce sujet ; à la rigueur, ce n'est même pas important,
dans la mesure qu'ils me fournissent un outil qui me sert bien. Mais
dans le temps, les développeurs de gcc avaient bien insisté sur le fait
qu'il n'était pas hosted pour ne pas prendre la responsibilité (ou la
blame) des bibliothèques qu'ils n'avaient pas écrites.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16


Avatar
espie
In article ,
wrote:
Quant à g++, je ne sais pas quelle est la position actuelle des
développeurs sur ce sujet ; à la rigueur, ce n'est même pas important,
dans la mesure qu'ils me fournissent un outil qui me sert bien. Mais
dans le temps, les développeurs de gcc avaient bien insisté sur le fait
qu'il n'était pas hosted pour ne pas prendre la responsibilité (ou la
blame) des bibliothèques qu'ils n'avaient pas écrites.


De plus en plus, le compilateur devient capable de sortir des diagnostics
precis. Avec les bons drapeaux, ca devient petit a petit une aide precieuse
a la portabilite.

IL manque juste cruellement des alternatives libres, histoire de ne pas se
retrouver a dependre sans faire expres d'un gcc'ism.

Avatar
espie
In article ,
DINH Viêt Hoà wrote:

Depuis quelques temps, g++ propose un drapeau -fhosted/-ffree-standing
qui, en plus des multiples -std=, est cense te permettre de choisir le
type d'implementation que tu veux.


d'ailleurs, j'ai peut-être une question un peu hors sujet mais si l'on
veut faire un code freestanding (par exemple un OS) en C++ (ce n'est pas
mon cas, rassurez-vous) avec g++. Quelles fonctions faut-il définir ?
Enfin ce que je veux demander plus précisément, c'est : quelle fonctions
C ou C++ sont supposées existantes dans la bibliothèque standard et que
g++ utilise pour implémenter les choses spécifiques au C++ (new, new[],
delete, delete[], d'autres ... ?).

Des gens connaissent-ils le prototype de ces fonctions ?


Dans les versions recentes de gcc, le support du runtime C++ a ete divise
en 2: la libstdc++ (version 3) et la libsupc++.

Precisement de maniere a ce que la libsupc++ contienne les petits bouts du
langage necessaire au code freestanding. A priori, le plus delicat ce
n'est pas tant new que les exceptions.

Cote libstdc++, comme James l'a souligne, la bibliotheque est fortement
dependante de l'OS sous-jacent quant aux aspects normalisation (et les gens
de GCC ne tiennent pas a en prendre la responsabilite, sauf erreur de ma
part). Par exemple, la gestion du multithreading, chere a James, est
fortement dependante des capacites de la libc sous-jacente. Dans le passe,
g++ faisait fortement ami-ami avec la glibc (et donc, impossible d'avoir
des entrees-sorties thread-safe sur un autre systeme). Je n'ai pas encore
eu le temps de me plonger dans le re-design complet que constitue la
libstdc++-v3. J'en espere beaucoup (trop ?).

(accessoirement, je ne sais pas si ce post est hors-sujet ou pas. Le theme
en est essentiellement `les aspects portabilite et normalisation de g++'.
Je ne vois pas trop ou en discuter a part ici)


Avatar
Gabriel Dos Reis
(Marc Espie) writes:

| part). Par exemple, la gestion du multithreading, chere a James, est
| fortement dependante des capacites de la libc sous-jacente. Dans le passe,
| g++ faisait fortement ami-ami avec la glibc (et donc, impossible d'avoir
| des entrees-sorties thread-safe sur un autre systeme). Je n'ai pas encore
| eu le temps de me plonger dans le re-design complet que constitue la
| libstdc++-v3. J'en espere beaucoup (trop ?).

Cela a été complètement refait, d'ailleurs beaucoup par des gens de
*BSD, pour tenir compte des machins sur ls système hôtes.

-- Gaby
1 2 3