Fonctions imbriquées en C

33 réponses
Avatar
Alain BARTHE
Bonsoir,

Une petite question sur les fonctions en C : depuis quand peut-on en C
imbriquer la définition d'une fonction à l'intérieur d'une autre ?

Je fais du C depuis plusieurs années et je suis tombé récemment sur un
truc du genre :

#include <stdio.h>

void main()
{
int i;

int f (int x)
{
return x * 3;
}

for (i = 0; i < 100; i++) printf ("%d = %d\n", i, f(i));
}

Ca peut-être assez pratique, pour ne pas polluer le code avec des
fonctions qui ne servent que dans une fonction donnée.

Je faisais des trucs du style en Pascal il y a bien longtemps, et je
savais que c'était autorisé en C++, mais je n'aurais jamais eu la
curiosité de le tester en C.

Pour info, ce code a été testé sous Linux avec gcc 4.1.2

10 réponses

1 2 3 4
Avatar
espie
In article <4c54a520$0$16565$,
Alain BARTHE wrote:
Bonsoir,

Une petite question sur les fonctions en C : depuis quand peut-on en C
imbriquer la définition d'une fonction à l'intérieur d'une autre ?



C'est une extension specifique a gcc.

Ca pose d'eventuels problemes. C'est implemente avec une technique appelee
"trampolines", qui necessite dans pas mal de cas de rendre la pile executable,
ce qui la rend nettement plus sensible aux attaques de type buffer-overflow...
Avatar
JKB
Le Sat, 31 Jul 2010 23:05:56 +0000 (UTC),
Marc Espie écrivait :
In article <4c54a520$0$16565$,
Alain BARTHE wrote:
Bonsoir,

Une petite question sur les fonctions en C : depuis quand peut-on en C
imbriquer la définition d'une fonction à l'intérieur d'une autre ?



C'est une extension specifique a gcc.

Ca pose d'eventuels problemes. C'est implemente avec une technique appelee
"trampolines", qui necessite dans pas mal de cas de rendre la pile executable,
ce qui la rend nettement plus sensible aux attaques de type buffer-overflow...



Que ce soit une extension, peut-être, je ne me suis jamais penché
sur ce problème. En revanche, je ne connais pas de compilo qui
refuse les fonctions imbriquées. gcc 2.7 l'autorisait déjà, DEC C
aussi, le compilo Sun n'est pas gêné... Aurais-tu des exemples ? Je
pose la question parce que pour une histoire de lisibilité,
j'utilise ça dans quelques programmes et je n'ai jamais eu un
utilisateur qui soit venu râler parce que la bibliothèque en
question refusait de compiler...

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Éric Lévénez
Le 01/08/10 10:22, JKB a écrit :
En revanche, je ne connais pas de compilo qui
refuse les fonctions imbriquées.



Je pense que Clang n'a pas cette extension.

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Avatar
JKB
Le Sun, 01 Aug 2010 10:37:25 +0200,
Éric Lévénez écrivait :
Le 01/08/10 10:22, JKB a écrit :
En revanche, je ne connais pas de compilo qui
refuse les fonctions imbriquées.



Je pense que Clang n'a pas cette extension.



Clang, c'est le truc utilisé par MacOS ? Si on parle bien de la même
chose, mes bouts de code compilent sans problème sous MacOS.

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Erwan David
JKB écrivait :

Le Sat, 31 Jul 2010 23:05:56 +0000 (UTC),
Marc Espie écrivait :
In article <4c54a520$0$16565$,
Alain BARTHE wrote:
Bonsoir,

Une petite question sur les fonctions en C : depuis quand peut-on en C
imbriquer la définition d'une fonction à l'intérieur d'une autre ?



C'est une extension specifique a gcc.

Ca pose d'eventuels problemes. C'est implemente avec une technique appelee
"trampolines", qui necessite dans pas mal de cas de rendre la pile executable,
ce qui la rend nettement plus sensible aux attaques de type buffer-overflow...



Que ce soit une extension, peut-être, je ne me suis jamais penché
sur ce problème. En revanche, je ne connais pas de compilo qui
refuse les fonctions imbriquées. gcc 2.7 l'autorisait déjà, DEC C
aussi, le compilo Sun n'est pas gêné... Aurais-tu des exemples ? Je
pose la question parce que pour une histoire de lisibilité,
j'utilise ça dans quelques programmes et je n'ai jamais eu un
utilisateur qui soit venu râler parce que la bibliothèque en
question refusait de compiler...



Le compilateur de Renesas pour H8S ne connait pas.

--
Le travail n'est pas une bonne chose. Si ça l'était,
les riches l'auraient accaparé
Avatar
Éric Lévénez
Le 01/08/10 10:39, JKB a écrit :
Le Sun, 01 Aug 2010 10:37:25 +0200,
Éric Lévénez écrivait :
Le 01/08/10 10:22, JKB a écrit :
En revanche, je ne connais pas de compilo qui
refuse les fonctions imbriquées.



Je pense que Clang n'a pas cette extension.



Clang, c'est le truc utilisé par MacOS ? Si on parle bien de la même
chose,



Non, Mac OS est mort depuis longtemps, personne ne développe sur ce
système aujourd'hui.

Clang+LLVM est utilisé sur Mac OS X et iOS. Le monde BSD, en particulier
FreeBSD, attend beaucoup de Clang pour remplacer GCC,

Une vidéo d'il y a 6 mois sur l'état de Clang :

<http://devimages.apple.com/llvm/videos/StateOfClang.mov>

mes bouts de code compilent sans problème sous MacOS.



Je n'ai pas testé les functions imbriquées, mais la doc dit qu'il n'y a
pas beaucoup d'intérêt à la chose et que son implémentation est placée
en fin de la liste des priorités de Clang.

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Avatar
Xavier Roche
Marc Espie a écrit :
Ca pose d'eventuels problemes. C'est implemente avec une technique appelee
"trampolines", qui necessite dans pas mal de cas de rendre la pile executable,
ce qui la rend nettement plus sensible aux attaques de type buffer-overflow...



Ah, intéressant. Les divers patchs de sécurité sous Linux (par exemple
celui intégré de grsecurity) proposent de rendre la pile non executable
(et empêcher que cela puisse être fait par des moyens détournés) ; et il
y a sur grsecurity une option d'émulation des "trampolines" gcc, justement.
Avatar
espie
In article <i33gk5$gi5$,
Xavier Roche wrote:
Marc Espie a écrit :
Ca pose d'eventuels problemes. C'est implemente avec une technique appelee
"trampolines", qui necessite dans pas mal de cas de rendre la pile executable,
ce qui la rend nettement plus sensible aux attaques de type buffer-overflow...



Ah, intéressant. Les divers patchs de sécurité sous Linux (par exemple
celui intégré de grsecurity) proposent de rendre la pile non executable
(et empêcher que cela puisse être fait par des moyens détournés) ; et il
y a sur grsecurity une option d'émulation des "trampolines" gcc, justement.



Tiens, je savais pas.

http://pax.grsecurity.net/docs/emutramp.txt

explique en detail ce que ca fait... terrain connu, et solutions connues.
Lorsqu'on a decide que la pile n'etait plus executable, dans OpenBSD, on a
reecrit le "trampoline" gestionnaire de signal, exactement comme ce qui est
decrit pour la glibc 2.1+...

Par contre, on ne s'est pas preoccupe d'emuler le code machine correspondant,
parce que ca va quand meme ramer un peu... et c'est un peu l'oppose de l'idee
des trampolines pour les fonctions imbriques.

A la place, on a demande a gcc de nous prevenir quand il generait des
trampolines (-Wtrampolines and -ftrampolines, options specifiques a gcc
sur OpenBSD). On s'est rendu compte que c'etait des mecanismes extremement
peu repandus, presque toujours remplaceable par autre chose... cas
particulier: certains compilateurs d'autres langages (GNU common-lisp de
memoire), qui generent du C contenant des fonctions imbriquees un peu partout.
Rien a faire dans ce cas-la: oblige de se manger les trampolines... de toutes
facons, c'est generalement le genre de trucs qui connait de bien trop pres
gcc et se permet des familiarites de goret avec celui-ci.

Note que les trampolines fonctionnent sur OpenBSD, suffit de mmaper le
bout de pile concerne avec PROT_EXEC, mais le compilateur refusera d'en
generer sans -ftrampolines.
Avatar
Patrick Texier
Le Sun, 1 Aug 2010 08:22:22 +0000 (UTC), JKB a écrit :

Que ce soit une extension, peut-être, je ne me suis jamais penché
sur ce problème. En revanche, je ne connais pas de compilo qui
refuse les fonctions imbriquées. gcc 2.7 l'autorisait déjà, DEC C
aussi, le compilo Sun n'est pas gêné... Aurais-tu des exemples ? Je
pose la question parce que pour une histoire de lisibilité,
j'utilise ça dans quelques programmes et je n'ai jamais eu un
utilisateur qui soit venu râler parce que la bibliothèque en
question refusait de compiler...



Borland C++ 5.5.1 n'a pas l'air d'aimer (-AT autorise ses extensions) :

C:cvim>make
MAKE Version 5.2 Copyright (c) 1987, 2000 Borland
bcc32 -O2 -OS -lGt -AT -c -omain.obj -w- -DWIN32 main.c
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
main.c:
Error E2141 main.c 8: Declaration syntax error in function main
Error E2379 main.c 12: Statement missing ; in function main
*** 2 errors in Compile ***

** error 1 ** deleting main.obj

Personnellement, je trouve cette construction horrible.
--
Patrick Texier

vim:syntax=mail:ai:ts=4:et:twr
Avatar
JKB
Le Sun, 01 Aug 2010 11:27:31 +0200,
Éric Lévénez écrivait :
Le 01/08/10 10:39, JKB a écrit :
Le Sun, 01 Aug 2010 10:37:25 +0200,
Éric Lévénez écrivait :
Le 01/08/10 10:22, JKB a écrit :
En revanche, je ne connais pas de compilo qui
refuse les fonctions imbriquées.



Je pense que Clang n'a pas cette extension.



Clang, c'est le truc utilisé par MacOS ? Si on parle bien de la même
chose,



Non, Mac OS est mort depuis longtemps, personne ne développe sur ce
système aujourd'hui.



Je sous-entendais naturellement MacOS X.

Clang+LLVM est utilisé sur Mac OS X et iOS. Le monde BSD, en particulier
FreeBSD, attend beaucoup de Clang pour remplacer GCC,

Une vidéo d'il y a 6 mois sur l'état de Clang :

<http://devimages.apple.com/llvm/videos/StateOfClang.mov>

> mes bouts de code compilent sans problème sous MacOS.

Je n'ai pas testé les functions imbriquées, mais la doc dit qu'il n'y a
pas beaucoup d'intérêt à la chose et que son implémentation est placée
en fin de la liste des priorités de Clang.



JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
=> http://grincheux.de-charybde-en-scylla.fr
1 2 3 4