OVH Cloud OVH Cloud

Conteneurs STL et thread-safety

21 réponses
Avatar
Marc Duflot
Bonjour à tous.

Comment ça va sur fclc++ depuis les années ?

Je débute avec la programmation multi-threaded. La preuve, j'ignore même
comment on dit « multi-threaded » ou « thread-safety » en français.

J'aimerais savoir quelles sont les garanties que les conteneurs de la
bibliothèque standard se comportent de la manière attendue dans un
programme multi-threaded. Je suis bien conscient que ce n'est
certainement pas précisé dans la norme du C++ mais en pratique, qu'en
est-il des compilateurs et bibliothèques actuelles ?

Pour donner un exemple, si je fais des insertions, lectures et
suppressions dans une std::map partagé pas plusieurs threads, est-il
nécessaire de placer des locks autour de ces opérations ?

Si cela a de l'importance, mon environnement de développement est le
compilateur Intel C++ avec parallélisation avec OpenMP sur Itanium 2. La
biblio est donc celle de dinkumware, dont la documentation précise
qu'elle est thread-safe (http://www.dinkumware.com/libcpp.html) mais
sans donner plus de garantie.

Merci.

10 réponses

1 2 3
Avatar
kanze
Gabriel Dos Reis wrote:
James Kanze writes:

| Gabriel Dos Reis wrote:
| > James Kanze writes:

| > | Ça dépend. Dans la pratique, je crois que la plupart
| > | (exception fait de g++) donne les même garanties que
| > | pour un objet de base (ou un tableau de type C).

| > Puisque tu répètes ceci dans tout ce fil, sans que je
| > puisse comprendre ce que tu voulais dire, je serais
| > heureux d'en voir un élaboration plus claire.

| Il faudrait que j'en fasse une FAQ -- c'est la troisième
| fois ce mois-ci qu'on me le démande:-).

désolé de pas suivre tes écrits à la virgules près ces
derniers temps -- il y a tellement de monde qui demande qu'on
les lise tous les jours que cela devient un vrai
embouteillage.


Pas de problème. Tu n'as apparamment pas vu le :-). Étant donné
que certaines des démandes ont été des email privés, c'est clair
que tu ne les as pas lu.

| Sans entrer dans tous les détails en ce qui concerne où il y
| a le problème dans le code (je te les fournirais si tu veux,
| mais ça risque d'ennuyer les autres ici, étant donné que
| c'est du propre à g++),

Puisque tu as jugé que cela n'ennuyerait pas les autres de
repéter cette remarque encore et encore, je crois qu'il est
tout à fait bienvenu et souhaité que tu donnes ces problèmes
ici. On pourra toujours arrêté si cela devient du hardcore.


Ce que je voulais dire, c'est que je ne voulais pas entrer ici
dans les détails du code G++ (ou libstdc++, plutôt).

Si on régarde à
http://gcc.gnu.org/onlinedocs/libstdc++/17_intro/howto.html#3,
on voit la phrase « We currently use the same definition that
SGI uses for their STL subset. However, the exception for
read-only containers only applies to the STL components. » C'est
assez ingenieux, étant donné que 1) SGI ne parle pas d'une «
exception », et 2) ce que SGI garantit n'est qu'une expression
de la garantie Posix, traduite en termes de C++. (Pour citer la
norme Posix : « Applications shall ensure that access to any
memory location by more than one thread of control (threads or
processes) is restricted such that no thread of control can read
or modify a memory location while another thread of control may
be modifying it. »)

D'après mes souvenirs, autrefois, le passage dans la
documentation libstdc++ était bien plus clair. On spécifiait
noir sur blanc les garanties de la bibliothèque libstdc++, et
ensuite, on signalait une garantie supplémentaire pour la partie
STL. Ça laissait ouvert la question : pourquoi est-ce qu'on n'a
pas jugé utile de fournir les même garanties, mais au moins, ça
rendait clair qu'on garantissait moins. Le texte aujourd'hui
cite seulement les garanties SGI, puis en parle d'une
exception ; à le lire, on dirait que la partie STL fournit moins
de garanties que la reste.

En tout cas, le fait reste que Posix fait un certain nombre de
garanties en ce qui concerne les threads. Il ne définit pas de
binding C++, ce qui laisse un peu en l'air ce qu'il faut faire
pour être conforme en C++, mais en général, ce n'est pas trop
difficile exterpoler (et dans au moins un cas où l'exterpolation
n'était pas évidente, ils ont ajouté du commentaire pour aider).
Par rapport à ce que dit Posix, g++ a au moins deux problèmes :
il n'appelle pas les destructeurs en cas de pthread_cancel (au
moins sous Solaris), et sa bibliothèque standard ne fournit pas
les garanties de base pour l'accès aux objets.

| le problème est simple : si j'ai une instance de std::string
| que je veux accéder depuis plusieurs threads, il faut que je
| synchronise les accès avec g++, même si aucun des accès ne
| modifie la chaîne.

???

Pas plus tard qu'hier, j'ai reçu un mail (avec copie à
d'autres maintainers de la GNU libstdc++ ainsi que Nathan
Myers, l'auteur principal de std::string dans GNU libstdc++,
et en CC: de ce message) reflétant des inquiétudes (FUD ?)
d'un utilisateur qui aurait lu des messages récents sur les
newsgroupes alléguant des propos proches de ceux que tu viens
de tenir -- je ne sais pas s'ils viennent de toi ou non, donc
ne saute pas au plafond avant d'avour lu la suite. La réponse
qu'il a reçue est en très grand contraste avec ce que tu
affirmes, alors j'apprecierais tu nous donnes plus de
précisions.


Question : est-ce qu'il est en désaccorde avec l'énoncé que tu
cites ? Si libstdc++ reclame qu'on peut accéder à une instance
de std::string depuis plusieurs threads, à condition de ne pas
la modifier, alors, il y a une erreur dans le code. Je ferais
donc un rapport d'erreur avec tous les détails, pour qu'on
essaie de la corriger. (Je dis « essayer », parce que je ne suis
pas convaincu qu'il soit possible de donner la garantie Posix
avec une implémentation COW et l'interface standard.) Jusqu'ici,
je ne l'ai pas fait parce que je croyais que c'était exprès ;
que libstdc++ ne faisait pas cette garantie. Et que donc, il ne
s'agissait pas d'une erreur de programmationm, mais d'un choix
conscient -- à mon avis, erroné (ce qui explique pourquoi
j'essaie tant à convaincre), mais un choix, néaumoins.

| Je suis prèsque sûr d'avoir vue quelque part dans la
| documentation g++ que c'est exprès -- que g++ ne veut pas
| donner d'avantage de garanties. Ce qui est dommage, parce
| que Posix, lui, en exige plus -- selon Posix, je peux
| accéder à un objet depuis plusieurs threads sans
| synchronisation externe dans la mésure qu'aucun thread ne
| modifie l'objet.

Et tu as fait des tests qui ont montré que cette guarantie ne
tien pas ? Si tu l'as fait, je serai (et sûrement Nathan Myers
aussi) curieux d'avoir des données plus précises -- au delà
d'un flou nébuleux. (Je reconnais d'avance que faire des tests
pour des programmes multi-thread n'est pas facile).


Si Nathan (ou d'autres) sont d'accord qu'on doit pouvoir accéder
à une instance de std::string depuis plusieurs threads, je me
ferais un plaisir à leur montrer le cas où ça ne marche pas ; si
je ne suis pas toujours d'accord avec lui sur des choix à faire,
je sais qu'il est assez intelligent pour comprendre le problème,
une fois qu'on lui le présente. Si je ne l'ai pas fait
jusqu'ici, et si je n'ai pas simplement fait un « bug report »,
sans le crier sur les toits, c'est que j'étais convaincu que
c'était un comportement voulu. Mais ça me ferait plaisir de
m'être trompé.

En somme, est-ce qu'il est l'intention que le code suivant
fonctionne, de façon garantie :

#include <pthread.h>
#include <iostream>
#include <ostream>
#include <string>

std::string g ;

extern "C" void*
thread1(
void* lock )
{
std::string t( g ) ;
pthread_mutex_lock( static_cast< pthread_mutex_t* >( lock ) ) ;
std::cout << t << 'n' ;
pthread_mutex_unlock( static_cast< pthread_mutex_t* >( lock ) )
;
return NULL ;
}

extern "C" void*
thread2(
void* lock )
{
std::string t( g.begin(), g.end() ) ;
pthread_mutex_lock( static_cast< pthread_mutex_t* >( lock ) ) ;
std::cout << t << 'n' ;
pthread_mutex_unlock( static_cast< pthread_mutex_t* >( lock ) )
;
return NULL ;
}

int
main()
{
g = "0123456789" ;
pthread_mutex_t lock ;
pthread_mutex_init( &lock, NULL ) ;
pthread_t t1 ;
if ( pthread_create( &t1, NULL, &thread1, &lock ) != 0 ) {
std::cerr << "Could not create thread1" << std::endl ;
}
pthread_t t2 ;
if ( pthread_create( &t2, NULL, &thread2, &lock ) != 0 ) {
std::cerr << "Could not create thread }
pthread_join( t1, NULL ) ;
pthread_join( t2, NULL ) ;
return 0 ;
}

Si oui, il y a une erreur dans la bibliothèque. (Mais
évidemment, la probabilité qu'elle pose réelement un problème
dans un programme aussi simple est extrèmement faible.)

Aussi, en passant... Le « burden of proof » est du côté de
celui qui reclame le thread-safety. Tant qu'on n'a pas prouvé
que le code est thread safe, il ne l'est pas. Mais ici, au moins
que je me trompe, le problème est ailleurs -- les auteurs de
libstdc++ ont décidé de créer leur propre définition de thread
safe, qui malheureusement n'est pas conforme à celle de Posix.
(Mais l'est, peut-être, à celle de Windows -- je n'ai jamais
réussi à trouver une documentation de ce que Windows prétend
garantir.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Gabriel Dos Reis
writes:

[...]

| > | Sans entrer dans tous les détails en ce qui concerne où il y
| > | a le problème dans le code (je te les fournirais si tu veux,
| > | mais ça risque d'ennuyer les autres ici, étant donné que
| > | c'est du propre à g++),
|
| > Puisque tu as jugé que cela n'ennuyerait pas les autres de
| > repéter cette remarque encore et encore, je crois qu'il est
| > tout à fait bienvenu et souhaité que tu donnes ces problèmes
| > ici. On pourra toujours arrêté si cela devient du hardcore.
|
| Ce que je voulais dire, c'est que je ne voulais pas entrer ici
| dans les détails du code G++ (ou libstdc++, plutôt).
|
| Si on régarde à
| http://gcc.gnu.org/onlinedocs/libstdc++/17_intro/howto.html#3,
| on voit la phrase « We currently use the same definition that
| SGI uses for their STL subset. However, the exception for
| read-only containers only applies to the STL components. » C'est
| assez ingenieux, étant donné que 1) SGI ne parle pas d'une «
| exception », et 2) ce que SGI garantit n'est qu'une expression
| de la garantie Posix, traduite en termes de C++. (Pour citer la
| norme Posix : « Applications shall ensure that access to any
| memory location by more than one thread of control (threads or
| processes) is restricted such that no thread of control can read
| or modify a memory location while another thread of control may
| be modifying it. »)
|
| D'après mes souvenirs, autrefois, le passage dans la
| documentation libstdc++ était bien plus clair. On spécifiait

Je ne sais pas. Très clairement la version de la bibliothèque de GCC
avant 2.95.x n'avait aucune gaurantie thread-safety -- de fait, était
connu comme ayant ces problèmes. Mais c'était connu comme V2

http://gcc.gnu.org/onlinedocs/libstdc++/faq/index.html#4_4_interface


| noir sur blanc les garanties de la bibliothèque libstdc++, et
| ensuite, on signalait une garantie supplémentaire pour la partie
| STL. Ça laissait ouvert la question : pourquoi est-ce qu'on n'a
| pas jugé utile de fournir les même garanties, mais au moins, ça
| rendait clair qu'on garantissait moins. Le texte aujourd'hui
| cite seulement les garanties SGI, puis en parle d'une
| exception ; à le lire, on dirait que la partie STL fournit moins
| de garanties que la reste.
|
| En tout cas, le fait reste que Posix fait un certain nombre de
| garanties en ce qui concerne les threads. Il ne définit pas de
| binding C++, ce qui laisse un peu en l'air ce qu'il faut faire
| pour être conforme en C++, mais en général, ce n'est pas trop
| difficile exterpoler (et dans au moins un cas où l'exterpolation
| n'était pas évidente, ils ont ajouté du commentaire pour aider).
| Par rapport à ce que dit Posix, g++ a au moins deux problèmes :
| il n'appelle pas les destructeurs en cas de pthread_cancel (au

Oui mais est-ce que Posix dit qu'il faut appeler le destructeur s'il y
a un pthread_cancel ?

http://www.codesourcery.com/archives/c++-pthreads/msg00001.html

Bnone lecture avant de me dire que je réponds à une autre question.

| moins sous Solaris), et sa bibliothèque standard ne fournit pas
| les garanties de base pour l'accès aux objets.
|
| > | le problème est simple : si j'ai une instance de std::string
| > | que je veux accéder depuis plusieurs threads, il faut que je
| > | synchronise les accès avec g++, même si aucun des accès ne
| > | modifie la chaîne.
|
| > ???
|
| > Pas plus tard qu'hier, j'ai reçu un mail (avec copie à
| > d'autres maintainers de la GNU libstdc++ ainsi que Nathan
| > Myers, l'auteur principal de std::string dans GNU libstdc++,
| > et en CC: de ce message) reflétant des inquiétudes (FUD ?)
| > d'un utilisateur qui aurait lu des messages récents sur les
| > newsgroupes alléguant des propos proches de ceux que tu viens
| > de tenir -- je ne sais pas s'ils viennent de toi ou non, donc
| > ne saute pas au plafond avant d'avour lu la suite. La réponse
| > qu'il a reçue est en très grand contraste avec ce que tu
| > affirmes, alors j'apprecierais tu nous donnes plus de
| > précisions.
|
| Question : est-ce qu'il est en désaccorde avec l'énoncé que tu
| cites ? Si libstdc++ reclame qu'on peut accéder à une instance
| de std::string depuis plusieurs threads, à condition de ne pas
| la modifier, alors, il y a une erreur dans le code. Je ferais
| donc un rapport d'erreur avec tous les détails, pour qu'on
| essaie de la corriger. (Je dis « essayer », parce que je ne suis
| pas convaincu qu'il soit possible de donner la garantie Posix
| avec une implémentation COW et l'interface standard.) Jusqu'ici,
| je ne l'ai pas fait parce que je croyais que c'était exprès ;
| que libstdc++ ne faisait pas cette garantie. Et que donc, il ne
| s'agissait pas d'une erreur de programmationm, mais d'un choix
| conscient -- à mon avis, erroné (ce qui explique pourquoi
| j'essaie tant à convaincre), mais un choix, néaumoins.

La réponse est que si tu penses qu'il y a un problème avec accès en
lecture (sans modification) concurrente il faut faire un rapport de
bug avec un cas de test. Nathan est en encore en CC: de ce message et
tu connais aussi son adresse.

-- Gaby
Avatar
kanze
Gabriel Dos Reis wrote:
writes:

[...]

| Si on régarde à
| http://gcc.gnu.org/onlinedocs/libstdc++/17_intro/howto.html#3,
| on voit la phrase « We currently use the same definition
| that SGI uses for their STL subset. However, the exception
| for read-only containers only applies to the STL components.
| » C'est assez ingenieux, étant donné que 1) SGI ne parle pas
| d'une « exception », et 2) ce que SGI garantit n'est qu'une
| expression de la garantie Posix, traduite en termes de C++.
| (Pour citer la norme Posix : « Applications shall ensure
| that access to any memory location by more than one thread
| of control (threads or processes) is restricted such that no
| thread of control can read or modify a memory location while
| another thread of control may be modifying it. »)

| D'après mes souvenirs, autrefois, le passage dans la
| documentation libstdc++ était bien plus clair. On spécifiait

Je ne sais pas. Très clairement la version de la bibliothèque
de GCC avant 2.95.x n'avait aucune gaurantie thread-safety --
de fait, était connu comme ayant ces problèmes.


Tu veux dire, avant 3.0, je crois. La bibliothèque livrée avec
2.95.2 ne faisait aucune prétention au thread-safety, je crois.
(C'était une implémentation à comptage de références sans le
moindre protection, avec une image d'une chaîne vide partagée
partout.)

Mais c'était connu comme V2


http://gcc.gnu.org/onlinedocs/libstdc++/faq/index.html#4_4_interface


J'avoue que pour moi, la bibliothèque, c'était partie de g++ ;
je me suis pas trop occupé de ses propres versions. (Mais je
suis un utilisateur, non un implémenteur.) À peu près la seule
exception, c'est que j'ai toujours reconnu qu'une partie de libc
venait du système (Solaris ou Linux), et non des développeurs
g++, et que donc, quand j'ai les idioties dans des en-têtes
comme stdio.h, je ne les signale pas comme des bugs de g++.

| noir sur blanc les garanties de la bibliothèque libstdc++,
| et ensuite, on signalait une garantie supplémentaire pour la
| partie STL. Ça laissait ouvert la question : pourquoi est-ce
| qu'on n'a pas jugé utile de fournir les même garanties, mais
| au moins, ça rendait clair qu'on garantissait moins. Le
| texte aujourd'hui cite seulement les garanties SGI, puis en
| parle d'une exception ; à le lire, on dirait que la partie
| STL fournit moins de garanties que la reste.

| En tout cas, le fait reste que Posix fait un certain nombre
| de garanties en ce qui concerne les threads. Il ne définit
| pas de binding C++, ce qui laisse un peu en l'air ce qu'il
| faut faire pour être conforme en C++, mais en général, ce
| n'est pas trop difficile exterpoler (et dans au moins un cas
| où l'exterpolation n'était pas évidente, ils ont ajouté du
| commentaire pour aider). Par rapport à ce que dit Posix, g++
| a au moins deux problèmes : il n'appelle pas les
| destructeurs en cas de pthread_cancel (au

Oui mais est-ce que Posix dit qu'il faut appeler le
destructeur s'il y a un pthread_cancel ?


Il ne dit pas qu'il faut -- Posix ignore le C++ dans la partie
normative.

Actuellement, le plus que je peux trouver, c'est la déclaration
dans la spécification de
pthread_cleanup_push/pthread_cleanup_pop que :

Note that the specified cleanup handling mechanism is
especially tied to the C language and, while the requirement
for a uniform mechanism for expressing cleanup is
language-independent, the mechanism used in other languages
may be quite different. In addition, this mechanism is
really only necessary due to the lack of a real exception
mechanism in the C language, which would be the ideal
solution.

Ça suggère fort qu'un cancel doit se mapper sur une exception
(qui évidemment appelera les destructeurs). On m'avait montré
quelque chose où C++ était nommé explicitement, mais je n'arrive
pas à le trouver à l'instant. De toute façon, il était du même
genre : une implémentation pourrait ...

En attendant, on est à la merci des définitions propre à chaque
système. Sous Solaris, par exemple, pthread_cancel ne donne pas
lieu à une exception que je saurais attraper, mais il appelle
bien les destructeurs.

http://www.codesourcery.com/archives/c++-pthreads/msg00001.html

Bnone lecture avant de me dire que je réponds à une autre
question.


Le problème n'est pas simple, je le sais. Pour un nombre de
raisons. Et je ne classifierais pas le comportement de g++ comme
une erreur. Mais le fait est qu'en tant qu'utilisateur, si les
destructeurs ne sont pas appelés lors d'un cancel, ça veut dire
que dans la pratique, je ne peux pas utiliser pthread_cancel (ou
je ne peux pas utiliser des classes avec un destructeur
non-trivial dans un thread qui risque d'être cancelé -- autant
programmer en C alors). Ce n'est pas très pratique, et avec Sun
CC, par exemple, ça ne pose pas de problèmes.

C'est quand même embêtant. Même si on sait qu'il peut pas y
avoir de solution définitive tant que Posix ignore le C++ et que
la norme C++ ignore les threads.

La réponse est que si tu penses qu'il y a un problème avec
accès en lecture (sans modification) concurrente il faut faire
un rapport de bug avec un cas de test. Nathan est en encore en
CC: de ce message et tu connais aussi son adresse.


D'accord. Il s'agit bien d'un cas où il n'y a pas le moindre
modification. Je ne peux pas fournir un programme qui déclenche
l'erreur systèmatiquement, ni même un qui la déclenche la
plupart du temps. Mais je crois qu'en montrant où ça ne marche
pas, et en expliquant le scénario, on le comprendra.

En passant, la FAQ que tu m'a cité a une autre définition, en
question 5.6 :

The user-code must guard against concurrent method calls
which may access any particular library object's state.

[...]

All library objects are safe to use in a multithreaded
program as long as each thread carefully locks out access by
any other thread while it uses any object visible to another
thread, i.e., treat library objects like any other shared
resource. In general, this requirement includes both read
and write access to objects; unless otherwise documented as
safe, do not assume that two threads may access a shared
standard library object at the same time.

Note bien l'utilisation du mot « accès ». Et l'erreur (au moins
en ce qui concerne Posix) : « treat library objects like any
other shared resource. » Posix n'exige de synchronisation des
accès que si au moins un des threads modifient l'objet.

Il y a aussi la définition de « modifier » à considérer. Dans
mon exemple, l'état interne de std::string a bien été modifié,
suite à l'appel d'une fonction non-const. Mais cette
modification est (normalement) invisible à un utilisateur qui ne
connaît pas l'implémentation.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Gabriel Dos Reis
writes:

| Gabriel Dos Reis wrote:
| > writes:
|
| > [...]
|
| > | Si on régarde à
| > | http://gcc.gnu.org/onlinedocs/libstdc++/17_intro/howto.html#3,
| > | on voit la phrase « We currently use the same definition
| > | that SGI uses for their STL subset. However, the exception
| > | for read-only containers only applies to the STL components.
| > | » C'est assez ingenieux, étant donné que 1) SGI ne parle pas
| > | d'une « exception », et 2) ce que SGI garantit n'est qu'une
| > | expression de la garantie Posix, traduite en termes de C++.
| > | (Pour citer la norme Posix : « Applications shall ensure
| > | that access to any memory location by more than one thread
| > | of control (threads or processes) is restricted such that no
| > | thread of control can read or modify a memory location while
| > | another thread of control may be modifying it. »)
|
| > | D'après mes souvenirs, autrefois, le passage dans la
| > | documentation libstdc++ était bien plus clair. On spécifiait
|
| > Je ne sais pas. Très clairement la version de la bibliothèque
| > de GCC avant 2.95.x n'avait aucune gaurantie thread-safety --
| > de fait, était connu comme ayant ces problèmes.
|
| Tu veux dire, avant 3.0, je crois.

Oui, tu as raison.

| La bibliothèque livrée avec
| 2.95.2 ne faisait aucune prétention au thread-safety, je crois.
| (C'était une implémentation à comptage de références sans le
| moindre protection, avec une image d'une chaîne vide partagée
| partout.)
|
| > Mais c'était connu comme V2
|
| >
| http://gcc.gnu.org/onlinedocs/libstdc++/faq/index.html#4_4_interface
|
| J'avoue que pour moi, la bibliothèque, c'était partie de g++ ;

Hmm. Jusqu'à la revolution EGCS, il était clair que la bibliothèque
de g++ étaitlivré séparemment : on installait d'abord GCC (qui
produisait CC, C++ Chill ansi que quelques autres langages); puis on
allait cherhcer libg++ qu'on compilait en croisant les doigts. On
pouvait utiliser autre chose comme bibliothèques.

Alors, dire que cela faisait partie de g++ sans distinction me semble
un peu pousser.

Puis, EGCS est arrivé. On avait plus à aller chercher libg++ dans un
coin obscure. Pour V3, j'ai pousser à une plus grande intégration de V3
dans GCC -- en reconnaissant qu'il y avait des arguments de ceux
qui voulaient une bibliothèque compilable avec un autre compilateur.

[...]

| > Oui mais est-ce que Posix dit qu'il faut appeler le
| > destructeur s'il y a un pthread_cancel ?
|
| Il ne dit pas qu'il faut -- Posix ignore le C++ dans la partie
| normative.
|
| Actuellement, le plus que je peux trouver, c'est la déclaration
| dans la spécification de
| pthread_cleanup_push/pthread_cleanup_pop que :
|
| Note that the specified cleanup handling mechanism is
| especially tied to the C language and, while the requirement
| for a uniform mechanism for expressing cleanup is
| language-independent, the mechanism used in other languages
| may be quite different. In addition, this mechanism is
| really only necessary due to the lack of a real exception
| mechanism in the C language, which would be the ideal
| solution.
|
| Ça suggère fort qu'un cancel doit se mapper sur une exception
| (qui évidemment appelera les destructeurs).

Oui et je suppose que tu as lu les arguments du thread que dont j'ai
donné la référence.

| On m'avait montré
| quelque chose où C++ était nommé explicitement, mais je n'arrive
| pas à le trouver à l'instant. De toute façon, il était du même
| genre : une implémentation pourrait ...
|
| En attendant, on est à la merci des définitions propre à chaque
| système. Sous Solaris, par exemple, pthread_cancel ne donne pas
| lieu à une exception que je saurais attraper, mais il appelle
| bien les destructeurs.

Le vrai problème ce n'est pas tellement d'appeler les destructeurs ou
non. Suppose que le système appelle les destructeurs. Après qu'est-ce
qu'il est censé faire ? Retourner le control à l'appelant par la voie
normale (retour de fonction) ? Ou dire à l'appelant qu'il faut qu'il
plie bagage (exception) ? Autant de questions, autant ed réponses. Et
avant de conclure que les développeurs de GCC s'en fichent je prierai
les gens de lire le thread (OK c'est long, mais la question n'est pas
simple) dont je redonne le lien

http://www.codesourcery.com/archives/c++-pthreads/msg00001.html

|
| > http://www.codesourcery.com/archives/c++-pthreads/msg00001.html
|
| > Bnone lecture avant de me dire que je réponds à une autre
| > question.
|
| Le problème n'est pas simple, je le sais. Pour un nombre de
| raisons. Et je ne classifierais pas le comportement de g++ comme
| une erreur. Mais le fait est qu'en tant qu'utilisateur, si les
| destructeurs ne sont pas appelés lors d'un cancel, ça veut dire

Les destructeurs non appelés, c'est un symptôme d'un problème plus
fondamental. Le problème a plusieurs facettes discutées dans le thread
ci-dessus.

There has been a fair amount of discussion on the GCC mailing list about
possibe ways of integrating POSIX threads with ISO C++.

The key question to date has been how to deal with thread cancellation.

People have asked questions like:

* Should cancellation throw an exception?

* What happens if the exception is caught, and not rethrown?

* What happens if the exception violates an exception-specification?

* What should be done about the fact that ISO C++ says that C library
functions like "printf" never throw exceptions?

Much of the GCC discussion can be found here:

http://gcc.gnu.org/ml/gcc/2003-12/msg00743.html

However, this issue is not specific to any compiler; it's a general
question about the interaction between C++ and POSIX threads, and
perhaps even other threading systems.

Therefore, we've started a new mailing list for discussing these
issues.

To post messages to the list, send mail to
c++

To unsubscribe, send mail to:
c++

The mailing list is archived and available on the web at:
http://www.codesourcery.com/archives/c++-pthreads/threads.html

| > La réponse est que si tu penses qu'il y a un problème avec
| > accès en lecture (sans modification) concurrente il faut faire
| > un rapport de bug avec un cas de test. Nathan est en encore en
| > CC: de ce message et tu connais aussi son adresse.
|
| D'accord. Il s'agit bien d'un cas où il n'y a pas le moindre

Je viens juste de lire ton PR.
Merci.

-- Gaby
Avatar
kanze
Gabriel Dos Reis wrote:
writes:


[...]
| J'avoue que pour moi, la bibliothèque, c'était partie de g++ ;

Hmm. Jusqu'à la revolution EGCS, il était clair que la
bibliothèque de g++ étaitlivré séparemment : on installait
d'abord GCC (qui produisait CC, C++ Chill ansi que quelques
autres langages); puis on allait cherhcer libg++ qu'on
compilait en croisant les doigts. On pouvait utiliser autre
chose comme bibliothèques.

Alors, dire que cela faisait partie de g++ sans distinction me
semble un peu pousser.


J'ai bien dit, « pour moi ». Je sais que dans la réalité, chez
tous les fournisseurs, c'est bien développé plus ou moins à
part, normalement par une équipe séparée. Donc, par exemple,
chez Sun, c'était Rogue Wave (et maintenant, c'est STLport),
chez Microsoft, c'est Dinkumware, etc. Mais en tant
qu'utilisateur, j'installe un « compilateur », et j'ai
tout. Quand j'ai un problème dans la bibliothèque de Sun CC (ce
qui arrive bien trop souvent), je m'adresse à Sun, exactement
comme quand j'ai un problème avec le compilateur.

Puis, EGCS est arrivé. On avait plus à aller chercher libg++
dans un coin obscure. Pour V3, j'ai pousser à une plus grande
intégration de V3 dans GCC -- en reconnaissant qu'il y avait
des arguments de ceux qui voulaient une bibliothèque
compilable avec un autre compilateur.


J'avoue que dans la mésure où la bibliothèque fait partie du
langage, je m'attends à la rétrouver avec le compilateur. J'ai
peut-être tort, mais c'est une habitude qui m'est resté de
l'époque où l'integration était totale, avec des langages comme
Fortran ou Pascal. Je ne m'attends pas à avoir à changer la
bibliothèque qui vient avec le compilateur.

[...]

| > Oui mais est-ce que Posix dit qu'il faut appeler le
| > destructeur s'il y a un pthread_cancel ?

| Il ne dit pas qu'il faut -- Posix ignore le C++ dans la
| partie normative.

| Actuellement, le plus que je peux trouver, c'est la déclaration
| dans la spécification de
| pthread_cleanup_push/pthread_cleanup_pop que :

| Note that the specified cleanup handling mechanism is
| especially tied to the C language and, while the requirement
| for a uniform mechanism for expressing cleanup is
| language-independent, the mechanism used in other languages
| may be quite different. In addition, this mechanism is
| really only necessary due to the lack of a real exception
| mechanism in the C language, which would be the ideal
| solution.

| Ça suggère fort qu'un cancel doit se mapper sur une
| exception (qui évidemment appelera les destructeurs).

Oui et je suppose que tu as lu les arguments du thread que
dont j'ai donné la référence.


Pas en détail, mais assez pour voir un peu d'où vient les
problèmes.

| On m'avait montré quelque chose où C++ était nommé
| explicitement, mais je n'arrive pas à le trouver à
| l'instant. De toute façon, il était du même genre : une
| implémentation pourrait ...

| En attendant, on est à la merci des définitions propre à
| chaque système. Sous Solaris, par exemple, pthread_cancel ne
| donne pas lieu à une exception que je saurais attraper, mais
| il appelle bien les destructeurs.

Le vrai problème ce n'est pas tellement d'appeler les
destructeurs ou non. Suppose que le système appelle les
destructeurs. Après qu'est-ce qu'il est censé faire ?
Retourner le control à l'appelant par la voie normale (retour
de fonction) ? Ou dire à l'appelant qu'il faut qu'il plie
bagage (exception) ?


Qu'est-ce qu'il fait en C ?

Autant de questions, autant de réponses. Et avant de conclure
que les développeurs de GCC s'en fichent je prierai les gens
de lire le thread (OK c'est long, mais la question n'est pas
simple) dont je redonne le lien

http://www.codesourcery.com/archives/c++-pthreads/msg00001.html


Je ne dis pas qu'ils s'en fiche. Je reconnais que le problème
n'est pas trivial. Si je croyais que c'était un problème clair
et net, j'aurais posté un rapport d'erreur.

Le problème, dans mon cas précis, c'est que je me trouve sur une
plateforme où le compilateur de référence n'est pas g++, et que
le compilateur de référence a défini un comportement précis, qui
est de remonter la pile en appelant les destructeurs (sans lever
une exception que je connais -- mais je n'ai pas cherché dans
tous les recoins de la doc).

| >
http://www.codesourcery.com/archives/c++-pthreads/msg00001.html


| > Bnone lecture avant de me dire que je réponds à une autre
| > question.

| Le problème n'est pas simple, je le sais. Pour un nombre de
| raisons. Et je ne classifierais pas le comportement de g++
| comme une erreur. Mais le fait est qu'en tant
| qu'utilisateur, si les destructeurs ne sont pas appelés lors
| d'un cancel, ça veut dire

Les destructeurs non appelés, c'est un symptôme d'un problème
plus fondamental. Le problème a plusieurs facettes discutées
dans le thread ci-dessus.


Je l'ai lu jusqu'à là.

There has been a fair amount of discussion on the GCC mailing list
about

possibe ways of integrating POSIX threads with ISO C++.

The key question to date has been how to deal with thread
cancellation.


People have asked questions like:

* Should cancellation throw an exception?

* What happens if the exception is caught, and not rethrown?

* What happens if the exception violates an
exception-specification?


* What should be done about the fact that ISO C++ says that
C library functions like "printf" never throw exceptions?


À l'exception de la dernière, ce sont toutes de bonnes
questions. En ce qui concerne la dernière : ISO C++ ne dit rien
de ce qui doit se passer dans printf dans un environement
multi-thread.

[Ce qui suit représente mon avis personnel. Je ne prétends
pas qu'il soit un fait absolu, mais il reflète mes pensées
actuelles sur le problème.]

En Posix C (qui n'est pas tout à fait ISO C), je peux pusher et
popper des fonctions de nettoyage. Il faut, selon Posix, que les
appels respectent le scope, qu'ils apparaissent en paires dans
la même portée lexique ; une implémentation « suggérée », c'e st
qu'elles soient en fait des macros où push ouvre une portée
(contient un {), et pop la ferme (contient le }). Posix dit
aussi que cette mechanisme est nécessitée par l'absence des
exceptions en C. J'interprète (mais je suppose que d'autres
interprétations sont possibles) que l'idée de base ici, qui leur
intéresse, c'est le fait que les exceptions nettoient ; le fait
qu'on peut l'attrapper est peut-être intéressant en général,
mais la mechanisme pthread_cleanup_push et pthread_cleanup_pop
ne fait rien pour en offrir la possibilité.

Dans ce sens, le mapping évident en C++ serait un espèce
d'exception qu'on ne peut pas attrapper. À l'exception près,
peut-être, de « catch ( ... ) » (mais alors, j'aimerais qu'on
garantisse un rethrow). Peut-être -- si le comportement
souhaitable me semble assez clair dans l'absences des catch, ce
les moins dans le cas des catch. Le problème, évidemment, c'est
qu'en C++, je peux bien utiliser RAII, mais je n'en suis pas
obligé ; je peux très bien utiliser des bloc catch(...) pour
libérer des ressources où s'assurer la cohérence. Interdire
d'« attrapper » ce que génère un pthread_cancel interdit
également ce genre de code.

Much of the GCC discussion can be found here:

http://gcc.gnu.org/ml/gcc/2003-12/msg00743.html

However, this issue is not specific to any compiler; it's a
general question about the interaction between C++ and
POSIX threads, and perhaps even other threading systems.


c'est une remarque très pertinante. En fait, il faudrait bien
qu'un jour ou l'autre, ou le comité ISO C++, ou Posix (ou les
deux) s'adresse au problème.

En attendant, si la décision de g++, c'est de ne rien
implémenter, parce qu'ils ne savent pas encore vraiment ce qu'il
faut implémenter, je la comprends et je l'accepte. Je dirais
seulement qu'un petit mot à cet effet dans la documentation
serait bien venu.

| > La réponse est que si tu penses qu'il y a un problème avec
| > accès en lecture (sans modification) concurrente il faut
| > faire un rapport de bug avec un cas de test. Nathan est en
| > encore en CC: de ce message et tu connais aussi son
| > adresse.

| D'accord. Il s'agit bien d'un cas où il n'y a pas le moindre

Je viens juste de lire ton PR.
Merci.


C'est moi qui te rémercies. J'étais parti sur l'idée que les
développeurs de g++ ne voulait pas en entendre plus à cet égard,
qu'ils considérait le comportement actuel correct et tout ce
qu'il fallait. (Il est correct, dans le sens qu'il est conforme
à la documentation. Correct ne veut pas forcement dire utile, ou
surtout ce que l'utilisateur est en droit de s'attendre:-).)

Ça me fait réelement plaisir de savoir que je me trompais.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Gabriel Dos Reis
writes:

| Gabriel Dos Reis wrote:
| > writes:
|
| [...]
| > | J'avoue que pour moi, la bibliothèque, c'était partie de g++ ;
|
| > Hmm. Jusqu'à la revolution EGCS, il était clair que la
| > bibliothèque de g++ étaitlivré séparemment : on installait
| > d'abord GCC (qui produisait CC, C++ Chill ansi que quelques
| > autres langages); puis on allait cherhcer libg++ qu'on
| > compilait en croisant les doigts. On pouvait utiliser autre
| > chose comme bibliothèques.
|
| > Alors, dire que cela faisait partie de g++ sans distinction me
| > semble un peu pousser.
|
| J'ai bien dit, « pour moi ».

J'ai bien lu cela. Mais le fait est qu'avant EGCS, tu avais g++
séparemment de libg++. Ce n'est pas seulement une situation où le
compilateur de Sun vient avec une biliothèque vendue par Rogue
Wave. Mais le fait que toi, utilisateur, si tu voulais utiliser g++,
avec <iostream.h> par exemple, tu devais installer g++, puis aller
chercher libg++ à part. Sun ou M$ ne t'oblige pas à faire une démarche
similaire.

Ma première installation de g++ était celle de gcc-2.7.1 (Nov 1995).
Malheureusement, je n'arrive pas à mettre la main sur le source.
Sur le site ftp, tu peux trouver par exemple le source de gcc-2.7.2.3
(pratiquement deux ans après 2.7.1) et les instrutions contenues dans
le fichier INSTALL me paraissent familières de l'époque (et je crois
qu'elles avaient vraiment positivement évolué)


Installing GNU CC
*****************

Here is the procedure for installing GNU CC on a Unix system. See
*Note VMS Install::, for VMS systems. In this section we assume you
compile in the same directory that contains the source files; see *Note
Other Dir::, to find out how to compile in a separate directory on Unix
systems.

You cannot install GNU C by itself on MSDOS; it will not compile
under any MSDOS compiler except itself. You need to get the complete
compilation package DJGPP, which includes binaries as well as sources,
and includes all the necessary compilation tools and libraries.

1. If you have built GNU CC previously in the same directory for a
different target machine, do `make distclean' to delete all files
that might be invalid. One of the files this deletes is
`Makefile'; if `make distclean' complains that `Makefile' does not
exist, it probably means that the directory is already suitably
clean.

2. On a System V release 4 system, make sure `/usr/bin' precedes
`/usr/ucb' in `PATH'. The `cc' command in `/usr/ucb' uses
libraries which have bugs.

3. Specify the host, build and target machine configurations. You do
this by running the file `configure'.

The "build" machine is the system which you are using, the "host"
machine is the system where you want to run the resulting compiler
(normally the build machine), and the "target" machine is the
system for which you want the compiler to generate code.

If you are building a compiler to produce code for the machine it
runs on (a native compiler), you normally do not need to specify
any operands to `configure'; it will try to guess the type of
machine you are on and use that as the build, host and target
machines. So you don't need to specify a configuration when
building a native compiler unless `configure' cannot figure out
what your configuration is or guesses wrong.

In those cases, specify the build machine's "configuration name"
with the `--build' option; the host and target will default to be
the same as the build machine. (If you are building a
cross-compiler, see *Note Cross-Compiler::.)

Here is an example:

./configure --build=sparc-sun-sunos4.1

A configuration name may be canonical or it may be more or less
abbreviated.

A canonical configuration name has three parts, separated by
dashes. It looks like this: `CPU-COMPANY-SYSTEM'. (The three
parts may themselves contain dashes; `configure' can figure out
which dashes serve which purpose.) For example,
`m68k-sun-sunos4.1' specifies a Sun 3.

You can also replace parts of the configuration by nicknames or
aliases. For example, `sun3' stands for `m68k-sun', so
`sun3-sunos4.1' is another way to specify a Sun 3. You can also
use simply `sun3-sunos', since the version of SunOS is assumed by
default to be version 4. `sun3-bsd' also works, since `configure'
knows that the only BSD variant on a Sun 3 is SunOS.

You can specify a version number after any of the system types,
and some of the CPU types. In most cases, the version is
irrelevant, and will be ignored. So you might as well specify the
version if you know it.

See *Note Configurations::, for a list of supported configuration
names and notes on many of the configurations. You should check
the notes in that section before proceeding any further with the
installation of GNU CC.

There are four additional options you can specify independently to
describe variant hardware and software configurations. These are
`--with-gnu-as', `--with-gnu-ld', `--with-stabs' and `--nfp'.

`--with-gnu-as'
If you will use GNU CC with the GNU assembler (GAS), you
should declare this by using the `--with-gnu-as' option when
you run `configure'.

Using this option does not install GAS. It only modifies the
output of GNU CC to work with GAS. Building and installing
GAS is up to you.

Conversely, if you *do not* wish to use GAS and do not specify
`--with-gnu-as' when building GNU CC, it is up to you to make
sure that GAS is not installed. GNU CC searches for a
program named `as' in various directories; if the program it
finds is GAS, then it runs GAS. If you are not sure where
GNU CC finds the assembler it is using, try specifying `-v'
when you run it.

The systems where it makes a difference whether you use GAS
are
`hppa1.0-ANY-ANY', `hppa1.1-ANY-ANY', `i386-ANY-sysv',
`i386-ANY-isc',
`i860-ANY-bsd', `m68k-bull-sysv', `m68k-hp-hpux',
`m68k-sony-bsd',
`m68k-altos-sysv', `m68000-hp-hpux', `m68000-att-sysv',
`ANY-lynx-lynxos', and `mips-ANY'). On any other system,
`--with-gnu-as' has no effect.

On the systems listed above (except for the HP-PA, for ISC on
the 386, and for `mips-sgi-irix5.*'), if you use GAS, you
should also use the GNU linker (and specify `--with-gnu-ld').

`--with-gnu-ld'
Specify the option `--with-gnu-ld' if you plan to use the GNU
linker with GNU CC.

This option does not cause the GNU linker to be installed; it
just modifies the behavior of GNU CC to work with the GNU
linker. Specifically, it inhibits the installation of
`collect2', a program which otherwise serves as a front-end
for the system's linker on most configurations.

`--with-stabs'
On MIPS based systems and on Alphas, you must specify whether
you want GNU CC to create the normal ECOFF debugging format,
or to use BSD-style stabs passed through the ECOFF symbol
table. The normal ECOFF debug format cannot fully handle
languages other than C. BSD stabs format can handle other
languages, but it only works with the GNU debugger GDB.

Normally, GNU CC uses the ECOFF debugging format by default;
if you prefer BSD stabs, specify `--with-stabs' when you
configure GNU CC.

No matter which default you choose when you configure GNU CC,
the user can use the `-gcoff' and `-gstabs+' options to
specify explicitly the debug format for a particular
compilation.

`--with-stabs' is meaningful on the ISC system on the 386,
also, if `--with-gas' is used. It selects use of stabs
debugging information embedded in COFF output. This kind of
debugging information supports C++ well; ordinary COFF
debugging information does not.

`--with-stabs' is also meaningful on 386 systems running
SVR4. It selects use of stabs debugging information embedded
in ELF output. The C++ compiler currently (2.6.0) does not
support the DWARF debugging information normally used on 386
SVR4 platforms; stabs provide a workable alternative. This
requires gas and gdb, as the normal SVR4 tools can not
generate or interpret stabs.

`--nfp'
On certain systems, you must specify whether the machine has
a floating point unit. These systems include
`m68k-sun-sunosN' and `m68k-isi-bsd'. On any other system,
`--nfp' currently has no effect, though perhaps there are
other systems where it could usefully make a difference.

The `configure' script searches subdirectories of the source
directory for other compilers that are to be integrated into GNU
CC. The GNU compiler for C++, called G++ is in a subdirectory
named `cp'. `configure' inserts rules into `Makefile' to build
all of those compilers.

Here we spell out what files will be set up by `configure'.
Normally you need not be concerned with these files.

* A file named `config.h' is created that contains a `#include'
of the top-level config file for the machine you will run the
compiler on (*note The Configuration File:
(gcc.info)Config.). This file is responsible for defining
information about the host machine. It includes `tm.h'.

The top-level config file is located in the subdirectory
`config'. Its name is always `xm-SOMETHING.h'; usually
`xm-MACHINE.h', but there are some exceptions.

If your system does not support symbolic links, you might
want to set up `config.h' to contain a `#include' command
which refers to the appropriate file.

* A file named `tconfig.h' is created which includes the
top-level config file for your target machine. This is used
for compiling certain programs to run on that machine.

* A file named `tm.h' is created which includes the
machine-description macro file for your target machine. It
should be in the subdirectory `config' and its name is often
`MACHINE.h'.

* The command file `configure' also constructs the file
`Makefile' by adding some text to the template file
`Makefile.in'. The additional text comes from files in the
`config' directory, named `t-TARGET' and `x-HOST'. If these
files do not exist, it means nothing needs to be added for a
given target or host.

4. The standard directory for installing GNU CC is `/usr/local/lib'.
If you want to install its files somewhere else, specify
`--prefix=DIR' when you run `configure'. Here DIR is a directory
name to use instead of `/usr/local' for all purposes with one
exception: the directory `/usr/local/include' is searched for
header files no matter where you install the compiler. To override
this name, use the `--local-prefix' option below.

5. Specify `--local-prefix=DIR' if you want the compiler to search
directory `DIR/include' for locally installed header files
*instead* of `/usr/local/include'.

You should specify `--local-prefix' *only* if your site has a
different convention (not `/usr/local') for where to put
site-specific files.

*Do not* specify `/usr' as the `--local-prefix'! The directory
you use for `--local-prefix' *must not* contain any of the
system's standard header files. If it did contain them, certain
programs would be miscompiled (including GNU Emacs, on certain
targets), because this would override and nullify the header file
corrections made by the `fixincludes' script.

6. Make sure the Bison parser generator is installed. (This is
unnecessary if the Bison output files `c-parse.c' and `cexp.c' are
more recent than `c-parse.y' and `cexp.y' and you do not plan to
change the `.y' files.)

Bison versions older than Sept 8, 1988 will produce incorrect
output for `c-parse.c'.

7. If you have chosen a configuration for GNU CC which requires other
GNU tools (such as GAS or the GNU linker) instead of the standard
system tools, install the required tools in the build directory
under the names `as', `ld' or whatever is appropriate. This will
enable the compiler to find the proper tools for compilation of
the program `enquire'.

Alternatively, you can do subsequent compilation using a value of
the `PATH' environment variable such that the necessary GNU tools
come before the standard system tools.

8. Build the compiler. Just type `make LANGUAGES=c' in the compiler
directory.

`LANGUAGES=c' specifies that only the C compiler should be
compiled. The makefile normally builds compilers for all the
supported languages; currently, C, C++ and Objective C. However,
C is the only language that is sure to work when you build with
other non-GNU C compilers. In addition, building anything but C
at this stage is a waste of time.

In general, you can specify the languages to build by typing the
argument `LANGUAGES="LIST"', where LIST is one or more words from
the list `c', `c++', and `objective-c'. If you have any
additional GNU compilers as subdirectories of the GNU CC source
directory, you may also specify their names in this list.

Ignore any warnings you may see about "statement not reached" in
`insn-emit.c'; they are normal. Also, warnings about "unknown
escape sequence" are normal in `genopinit.c' and perhaps some
other files. Likewise, you should ignore warnings about "constant
is so large that it is unsigned" in `insn-emit.c' and
`insn-recog.c' and a warning about a comparison always being zero
in `enquire.o'. Any other compilation errors may represent bugs in
the port to your machine or operating system, and should be
investigated and reported.

Some commercial compilers fail to compile GNU CC because they have
bugs or limitations. For example, the Microsoft compiler is said
to run out of macro space. Some Ultrix compilers run out of
expression space; then you need to break up the statement where
the problem happens.

9. If you are building a cross-compiler, stop here. *Note
Cross-Compiler::.

10. Move the first-stage object files and executables into a
subdirectory with this command:

make stage1

The files are moved into a subdirectory named `stage1'. Once
installation is complete, you may wish to delete these files with
`rm -r stage1'.

11. If you have chosen a configuration for GNU CC which requires other
GNU tools (such as GAS or the GNU linker) instead of the standard
system tools, install the required tools in the `stage1'
subdirectory under the names `as', `ld' or whatever is
appropriate. This will enable the stage 1 compiler to find the
proper tools in the following stage.

Alternatively, you can do subsequent compilation using a value of
the `PATH' environment variable such that the necessary GNU tools
come before the standard system tools.

12. Recompile the compiler with itself, with this command:

make CC="stage1/xgcc -Bstage1/" CFLAGS="-g -O2"

This is called making the stage 2 compiler.

The command shown above builds compilers for all the supported
languages. If you don't want them all, you can specify the
languages to build by typing the argument `LANGUAGES="LIST"'. LIST
should contain one or more words from the list `c', `c++',
`objective-c', and `proto'. Separate the words with spaces.
`proto' stands for the programs `protoize' and `unprotoize'; they
are not a separate language, but you use `LANGUAGES' to enable or
disable their installation.

If you are going to build the stage 3 compiler, then you might
want to build only the C language in stage 2.

Once you have built the stage 2 compiler, if you are short of disk
space, you can delete the subdirectory `stage1'.

On a 68000 or 68020 system lacking floating point hardware, unless
you have selected a `tm.h' file that expects by default that there
is no such hardware, do this instead:

make CC="stage1/xgcc -Bstage1/" CFLAGS="-g -O2 -msoft-float"

13. If you wish to test the compiler by compiling it with itself one
more time, install any other necessary GNU tools (such as GAS or
the GNU linker) in the `stage2' subdirectory as you did in the
`stage1' subdirectory, then do this:

make stage2
make CC="stage2/xgcc -Bstage2/" CFLAGS="-g -O2"

This is called making the stage 3 compiler. Aside from the `-B'
option, the compiler options should be the same as when you made
the stage 2 compiler. But the `LANGUAGES' option need not be the
same. The command shown above builds compilers for all the
supported languages; if you don't want them all, you can specify
the languages to build by typing the argument `LANGUAGES="LIST"',
as described above.

If you do not have to install any additional GNU tools, you may
use the command

make bootstrap LANGUAGES=LANGUAGE-LIST BOOT_CFLAGS=OPTION-LIST

instead of making `stage1', `stage2', and performing the two
compiler builds.

14. Then compare the latest object files with the stage 2 object
files--they ought to be identical, aside from time stamps (if any).

On some systems, meaningful comparison of object files is
impossible; they always appear "different." This is currently
true on Solaris and some systems that use ELF object file format.
On some versions of Irix on SGI machines and DEC Unix (OSF/1) on
Alpha systems, you will not be able to compare the files without
specifying `-save-temps'; see the description of individual
systems above to see if you get comparison failures. You may have
similar problems on other systems.

Use this command to compare the files:

make compare

This will mention any object files that differ between stage 2 and
stage 3. Any difference, no matter how innocuous, indicates that
the stage 2 compiler has compiled GNU CC incorrectly, and is
therefore a potentially serious bug which you should investigate
and report.

If your system does not put time stamps in the object files, then
this is a faster way to compare them (using the Bourne shell):

for file in *.o; do
cmp $file stage2/$file
done

If you have built the compiler with the `-mno-mips-tfile' option on
MIPS machines, you will not be able to compare the files.

15. Install the compiler driver, the compiler's passes and run-time
support with `make install'. Use the same value for `CC',
`CFLAGS' and `LANGUAGES' that you used when compiling the files
that are being installed. One reason this is necessary is that
some versions of Make have bugs and recompile files gratuitously
when you do this step. If you use the same variable values, those
files will be recompiled properly.

For example, if you have built the stage 2 compiler, you can use
the following command:

make install CC="stage2/xgcc -Bstage2/" CFLAGS="-g -O" LANGUAGES="LIST"

This copies the files `cc1', `cpp' and `libgcc.a' to files `cc1',
`cpp' and `libgcc.a' in the directory
`/usr/local/lib/gcc-lib/TARGET/VERSION', which is where the
compiler driver program looks for them. Here TARGET is the target
machine type specified when you ran `configure', and VERSION is
the version number of GNU CC. This naming scheme permits various
versions and/or cross-compilers to coexist.

This also copies the driver program `xgcc' into
`/usr/local/bin/gcc', so that it appears in typical execution
search paths.

On some systems, this command causes recompilation of some files.
This is usually due to bugs in `make'. You should either ignore
this problem, or use GNU Make.

*Warning: there is a bug in `alloca' in the Sun library. To avoid
this bug, be sure to install the executables of GNU CC that were
compiled by GNU CC. (That is, the executables from stage 2 or 3,
not stage 1.) They use `alloca' as a built-in function and never
the one in the library.*

(It is usually better to install GNU CC executables from stage 2
or 3, since they usually run faster than the ones compiled with
some other compiler.)

16. If you're going to use C++, it's likely that you need to also
install the libg++ distribution. It should be available from the
same place where you got the GNU C distribution. Just as GNU C
does not distribute a C runtime library, it also does not include
a C++ run-time library. All I/O functionality, special class
libraries, etc., are available in the libg++ distribution.

Note bien l'instruction 16.

Aujourd'hui, il suffit de faire

gcc-x.y.z/configure && make && make install

et on a des compilateurs pour C, C++ + bibliothèque, ObjC, Fortran,
Java + bibliothèque.
Et les gens se plaignent :-/

-- Gaby
Avatar
kanze
Gabriel Dos Reis wrote:

[...]
16. If you're going to use C++, it's likely that you need to also
install the libg++ distribution. It should be available from
the

same place where you got the GNU C distribution. Just as GNU
C

does not distribute a C runtime library, it also does not
include

a C++ run-time library. All I/O functionality, special class
libraries, etc., are available in the libg++ distribution.

Note bien l'instruction 16.


Je ne mettais pas ta parole en doute. C'est simplement que
jusqu'il y a fort peu, si je voulais g++ chez moi, je récupérer
une des versions tout faites sur un SunSite, et je l'installais
comme n'importe quel logiciel de Sun. Chez les clients, c'était
toujours le client qui l'avait installé.

Aujourd'hui, il suffit de faire

gcc-x.y.z/configure && make && make install

et on a des compilateurs pour C, C++ + bibliothèque, ObjC, Fortran,
Java + bibliothèque.
Et les gens se plaignent :-/


Moi non. Il y a un temps, je crois que j'ai essayé d'installer
un g++ depuis les sources, et j'y ai renouncé, parce qu'il y
avait trop de démarches manuelles. Mais ce n'est pas récemment ;
depuis un moment, je fais à peu près ce que tu dis, et ça
marche.

Tu exagères quand même un peu -- selon la documentation de
l'installation, il vaut mieux générer dans un répertoire à part.
Et sur Linux, selon ce qu'on fait, il faut choisir telle ou
telle option -- j'ai dû régénérer plusieurs fois parce que je ne
le savais pas, et je l'ai appris du forum d'aide g++. En
revanche, à part l'histoire du répertoire, ça semble propre à
Linux ; je n'ai jamais eu de problèmes pareils sous Solaris, où
tout sauf pthread_cancel marche comme on s'y attendrait:-).

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Gabriel Dos Reis
writes:


[...]

| > Aujourd'hui, il suffit de faire
|
| > gcc-x.y.z/configure && make && make install

[...]

| Tu exagères quand même un peu -- selon la documentation de
| l'installation, il vaut mieux générer dans un répertoire à part.

Ah, mais si tu regardes la commande que j'ai écrite, je n'ai pas mis
./configure
:-)

C'est un bug connu que GCC est le seul logicial de GNU qui ne supporte
pas "in source configuration".

| Et sur Linux, selon ce qu'on fait, il faut choisir telle ou
| telle option -- j'ai dû régénérer plusieurs fois parce que je ne
| le savais pas, et je l'ai appris du forum d'aide g++. En

mais c'est quand même moins pénible qu'il y a 8 ou 10 ans.

-- Gaby
Avatar
James Kanze
Gabriel Dos Reis wrote:
writes:


[...]


| > Aujourd'hui, il suffit de faire


| > gcc-x.y.z/configure && make && make install


[...] | Tu exagères quand même un peu -- selon la
documentation de | l'installation, il vaut mieux générer dans
un répertoire à part.


Ah, mais si tu regardes la commande que j'ai écrite, je n'ai
pas mis
./configure
:-)


Oui, mais tu as oublié le mkdir:-).

C'est un bug connu que GCC est le seul logicial de GNU qui ne
supporte pas "in source configuration".


Peut-être, mais c'est un bug avec lequel je peux vivre:-).

| Et sur Linux, selon ce qu'on fait, il faut choisir telle ou
| telle option -- j'ai dû régénérer plusieurs fois parce que
| je ne le savais pas, et je l'ai appris du forum d'aide g++.
| En


mais c'est quand même moins pénible qu'il y a 8 ou 10 ans.


Il y a 8 ou 10 ans sur Linux ? Je te crois -- à l'époque, je
crois que les gens compilaient le noyau eux-mêmes.

Aussi, il faut dire que j'ai une certaine préjudice. Ça fait
quinze ans que je travaille principalement sous Solaris. Alors,
je sais exactement où il faut chercher tout, quel fichier
configure quoi, etc. Avec Linux, je me doute que tel ou tel
fichier existe, mais je ne sais pas où, ni même forcément
comment il s'appelle.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34

Avatar
Gabriel Dos Reis
James Kanze writes:

[...]

| > | Et sur Linux, selon ce qu'on fait, il faut choisir telle ou
| > | telle option -- j'ai dû régénérer plusieurs fois parce que
| > | je ne le savais pas, et je l'ai appris du forum d'aide g++.
| > | En
|
| > mais c'est quand même moins pénible qu'il y a 8 ou 10 ans.
|
| Il y a 8 ou 10 ans sur Linux ?

Sun OS, Solaris.

| Je te crois -- à l'époque, je
| crois que les gens compilaient le noyau eux-mêmes.

Mais c'est indépendant -- je continue à compiler le noyau :-)

-- Gaby
1 2 3