Créer un compteSe connecter
malloc est probablement l'origine principale du déclin de la qualité des logiciels ces 30 dernières années, non seulement à cause de C, mais aussi à travers la pléthore de langage systèmes et libraries qui en sont dépendants.
la façon dont malloc et ses fonctions sœurs realloc et free fonctionnent est diamétralement opposé au fonctionnement de la mémoire sur la plupart des systèmes (j'entends par là tous les systèmes qui passent par de MMU ou un équivalent).

En programmation, malloc est une fonction d'allocation pour utilisateur, autrement dit, une interface avec le kernel pour allouer de la mémoire aux processus utilisateurs. Cette interface introduit une couche supplémentaire de complexité, principalement pour deux raison, la première étant la façon dont les allocateurs pour le kernel gèrent la mémoire. malloc se connecte au kernel pour allouer la mémoire que vous demandez, mais il ajoute sa propre couche de conneries pour deux raisons:

La première est que les allocateurs pour le kernel opèrent sur des pages et non des octets individuels. Qu'est-ce qu'une page ? Cela dépend de votre matériel et de votre configuration (la taille habituelle est de 4KiB soit 4096 octets, mais depuis 20ans, les CPU (MMU, en fait) ont la capacité de fonctionner sur des pages de 2 MiB et 1 GiB. Quel est l'avantage de ces pages ? Vous vous souvenez quand j'ai dit que la plupart des systèmes effectuent une traduction d'adresses virtuelles (MMU) ? Oui, ces traductions sont stockées en mémoire dans une table de pages que le noyau gère pour votre processus et dans laquelle sont répertoriées toutes les régions d'adresses auxquelles votre programme est censé avoir accès. Si elle n'y figure pas, vous ne pouvez pas y accéder. Si elle y figure, il se peut que vous ne puissiez toujours pas y accéder, en fonction des privilèges de votre programme sur cette page. Ce n'est pas un problème linux ou windows d'ailleurs, c'est juste la façon dont le matériel fonctionne, il y a des registres spéciaux et tout le reste pour cette merde.

Le problème, c'est que la consultation de cette table est très lente pour le MMU (quelques milliers de cycles, voire plus). C'est pourquoi il conserve les traductions récentes dans un cache proche du processeur (le TLB). Le problème du TLB c'est qu'il est situé sur le processeur, il est donc petit comme tout ce qui le processeur. Vous vous retrouvez donc avec un nombre limité de traductions avant qu'il ne doive expulser les entrées plus anciennes. Les entrées que vous avez peut-être encore utilisées et qui doivent maintenant être récupérées au cours d'un nouveau long parcours de la table des pages.
Des pages plus grandes réduisent le nombre d'entrées que la TLB doit garder en mémoire, ce qui permet de réduire le nombre d'allers-retours. Au lieu d'utiliser 514 traductions de pages de 4Ko, on peut utiliser une seule page de 2Mo qui le travail tout aussi bien, voire mieux (parce qu'elle ne doit être récupérée qu'une seule fois, et non 511 fois de plus).

Contrairement à tout cela, malloc permet d'utiliser des allocations à l'octet prêt. La belle affaire.

La deuxième chose que malloc fait pour vous et qui nécessite sa couche d'abstractions douteuse dans l'espace utilisateur, c'est la gestion des lifetimes. Et c'est très bien fait, votre page peut héberger des milliers d'allocations relativement petites, qui ont chacune leur propre durée de vie, vous pouvez en libérer certaines en réallouer d'autres, en libérer d'autres, en allouer une nouvelle, c'est très générique. Le problème c'est que la plupart du temps, les gens, et par là je veux dire les développeurs qui devraient savoir en théorie leurs besoins, sont ignorants. Chaque fois que le besoin d'allouer de la mémoire se fait sentir, ils utilisent une très petite liste de contrôle qui ne comporte que deux éléments : la pile et malloc. Si c'est trop gros : malloc. S'il y a une lifetime particulière : malloc. C'est tout.

Et puis il y a le multithreading. Tout ce que fait malloc ne nécessite pas d'atomicité ou de threadlock, mais certaines choses que l'on doit garder en mémoire dans des structures globales se briseraient si plusieurs threads essayaient d'y accéder (malloc a donc besoin de son propre système de thread lock en plus de celui fourni par le kernel par lequel les entrées de la table des pages sont protégées).
Un appel gratuit à malloc, même si la mémoire est déjà disponible en mode utilisateur, malloc prend facilement plus de 1000 cycles.
La meilleure façon de châtier les hommes est de toujours donner ce qu'ils réclament.
il y a 2 ans
Gardez également à l'esprit que l'allocation n'est qu'une partie du problème. Chaque appel à malloc nécessite un appel égal pour libérer la mémoire allouée ; il n'y a aucun moyen de dire à malloc de placer la prochaine allocation dans un pool spécifique d'objets qui partagent la même durée de vie (parce que malloc n'expose pas ces buffers/mappings/arenas), ce qui rendrait la libération de ces objets triviale. Non, vous devez passer en revue chaque objet et le libérer vous-même.
La meilleure façon de châtier les hommes est de toujours donner ce qu'ils réclament.
il y a 2 ans
:Doshin:
il y a 2 ans
arrete de coder en c et casse pas les couilles surtout
:Chamite:
il y a 2 ans
C’est le nouveau compte d’Antoineforum ?
:zahi:
il y a 2 ans
Malloc ouilles
:pitiemoman:
il y a 2 ans
Yoneda
Yoneda
2 ans
malloc est probablement l'origine principale du déclin de la qualité des logiciels ces 30 dernières années, non seulement à cause de C, mais aussi à travers la pléthore de langage systèmes et libraries qui en sont dépendants.
la façon dont malloc et ses fonctions sœurs realloc et free fonctionnent est diamétralement opposé au fonctionnement de la mémoire sur la plupart des systèmes (j'entends par là tous les systèmes qui passent par de MMU ou un équivalent).

En programmation, malloc est une fonction d'allocation pour utilisateur, autrement dit, une interface avec le kernel pour allouer de la mémoire aux processus utilisateurs. Cette interface introduit une couche supplémentaire de complexité, principalement pour deux raison, la première étant la façon dont les allocateurs pour le kernel gèrent la mémoire. malloc se connecte au kernel pour allouer la mémoire que vous demandez, mais il ajoute sa propre couche de conneries pour deux raisons:

La première est que les allocateurs pour le kernel opèrent sur des pages et non des octets individuels. Qu'est-ce qu'une page ? Cela dépend de votre matériel et de votre configuration (la taille habituelle est de 4KiB soit 4096 octets, mais depuis 20ans, les CPU (MMU, en fait) ont la capacité de fonctionner sur des pages de 2 MiB et 1 GiB. Quel est l'avantage de ces pages ? Vous vous souvenez quand j'ai dit que la plupart des systèmes effectuent une traduction d'adresses virtuelles (MMU) ? Oui, ces traductions sont stockées en mémoire dans une table de pages que le noyau gère pour votre processus et dans laquelle sont répertoriées toutes les régions d'adresses auxquelles votre programme est censé avoir accès. Si elle n'y figure pas, vous ne pouvez pas y accéder. Si elle y figure, il se peut que vous ne puissiez toujours pas y accéder, en fonction des privilèges de votre programme sur cette page. Ce n'est pas un problème linux ou windows d'ailleurs, c'est juste la façon dont le matériel fonctionne, il y a des registres spéciaux et tout le reste pour cette merde.

Le problème, c'est que la consultation de cette table est très lente pour le MMU (quelques milliers de cycles, voire plus). C'est pourquoi il conserve les traductions récentes dans un cache proche du processeur (le TLB). Le problème du TLB c'est qu'il est situé sur le processeur, il est donc petit comme tout ce qui le processeur. Vous vous retrouvez donc avec un nombre limité de traductions avant qu'il ne doive expulser les entrées plus anciennes. Les entrées que vous avez peut-être encore utilisées et qui doivent maintenant être récupérées au cours d'un nouveau long parcours de la table des pages.
Des pages plus grandes réduisent le nombre d'entrées que la TLB doit garder en mémoire, ce qui permet de réduire le nombre d'allers-retours. Au lieu d'utiliser 514 traductions de pages de 4Ko, on peut utiliser une seule page de 2Mo qui le travail tout aussi bien, voire mieux (parce qu'elle ne doit être récupérée qu'une seule fois, et non 511 fois de plus).

Contrairement à tout cela, malloc permet d'utiliser des allocations à l'octet prêt. La belle affaire.

La deuxième chose que malloc fait pour vous et qui nécessite sa couche d'abstractions douteuse dans l'espace utilisateur, c'est la gestion des lifetimes. Et c'est très bien fait, votre page peut héberger des milliers d'allocations relativement petites, qui ont chacune leur propre durée de vie, vous pouvez en libérer certaines en réallouer d'autres, en libérer d'autres, en allouer une nouvelle, c'est très générique. Le problème c'est que la plupart du temps, les gens, et par là je veux dire les développeurs qui devraient savoir en théorie leurs besoins, sont ignorants. Chaque fois que le besoin d'allouer de la mémoire se fait sentir, ils utilisent une très petite liste de contrôle qui ne comporte que deux éléments : la pile et malloc. Si c'est trop gros : malloc. S'il y a une lifetime particulière : malloc. C'est tout.

Et puis il y a le multithreading. Tout ce que fait malloc ne nécessite pas d'atomicité ou de threadlock, mais certaines choses que l'on doit garder en mémoire dans des structures globales se briseraient si plusieurs threads essayaient d'y accéder (malloc a donc besoin de son propre système de thread lock en plus de celui fourni par le kernel par lequel les entrées de la table des pages sont protégées).
Un appel gratuit à malloc, même si la mémoire est déjà disponible en mode utilisateur, malloc prend facilement plus de 1000 cycles.
trolon
:onche:
il y a 2 ans
En bref, n'utilisez malloc que si vous avez absolument besoin que vos objets aient une durée de individuelle. Dans les langages haut niveau, plutôt que de fusionner les durées de vie, on utilise un système de références, le RAII ou un garbage collector pour s'assurer que la mémoire est libérée chaque fois qu'elle sort du champ de l'application. La raison en est que les compilateurs/interpréteurs/machines virtuelles sont très mauvais pour fusionner des objets ayant la même durée de vie. Ils peuvent en garder la trace, mais ils ne peuvent pas les fusionner. Mais deviner qui sait exactement quelles sont les durées de vie de certains objets, lesquels peuvent être fusionner directement.

Mais deviner qui sait exactement quelles sont les durées de vie de chaque objet, lesquels peuvent être fusionnés et lesquels ne peuvent pas l'être ? Vous. De plus, soit vous le savez, auquel cas vous pouvez allouer la quantité exacte d'octets, soit vous ne le savez pas, auquel cas vous devez passer par le ridicule qu'est la réallocation.

Au début, j'ai écrit que malloc a besoin du kernel pour allouer la mémoire qu'il vous remet. La façon de procéder est bien documentée pour windows et linux avec ces fonctions :

LPVOID VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize,
DWORD flAllocationType, DWORD flProtect);
void *mmap(void addr, size_t length, int prot, int flags, int fd, off_t offset);

L'avantage de ces allocateurs est qu'ils ne permettent pas seulement d'allouer de la mémoire, mais aussi et surtout de l'espace d'adressage virtuel, dont nous disposons en abondance sur nos processeurs 64 bits. L'allocation d'un espace d'adressage virtuel indique simplement au kernel que cette plage est la vôtre maintenant, et vous ne voulez pas que le kernel renvoie des adresses dans cette plage à moins que vous ne le lui demandiez explicitement. Il est très facile pour le kernel d'en garder la trace et, de ce fait, une simple réservation ne nécessite pas beaucoup de mémoire.
La meilleure façon de châtier les hommes est de toujours donner ce qu'ils réclament.
il y a 2 ans
Ces étapes sont probablement obligatoire,je ne sais pas si il y aura un jour un autre moyen d'avoir le même résultat
Collector
:Michel_blanc:
il y a 2 ans
arrete de coder en c et casse pas les couilles surtout
:Chamite:
on peut utiliser C sans malloc
La meilleure façon de châtier les hommes est de toujours donner ce qu'ils réclament.
il y a 2 ans
Ah oui les pages ... C'était un de les tp en L3. Mais j'ai pas souvenir d'un quelconque lien avec malloc.

On croit faire du bas niveau en allouant de la mémoire avec malloc mais il y a toujours plus bas niveau
:hap:
comme quoi .

Par contre je vois pas vraiment où est le problème, comment faire mieux ? Pouvoir indiquer des pools d'allocations à malloc si on connait le lifetime de nos objets ?
Seugondaire, Duce des #hypernarboreens, Ecoutant de la #confrerie-noire.
il y a 2 ans
Khey
Khey
2 ans
Ces étapes sont probablement obligatoire,je ne sais pas si il y aura un jour un autre moyen d'avoir le même résultat
on peut avoir le même résultat avec mmap
La meilleure façon de châtier les hommes est de toujours donner ce qu'ils réclament.
il y a 2 ans
Ah oui les pages ... C'était un de les tp en L3. Mais j'ai pas souvenir d'un quelconque lien avec malloc.

On croit faire du bas niveau en allouant de la mémoire avec malloc mais il y a toujours plus bas niveau
:hap:
comme quoi .

Par contre je vois pas vraiment où est le problème, comment faire mieux ? Pouvoir indiquer des pools d'allocations à malloc si on connait le lifetime de nos objets ?
le problème ce n'est pas tant malloc mais la façon dont les gens l'utilisent comme solution par défaut pour allouer de la mémoire.
La meilleure façon de châtier les hommes est de toujours donner ce qu'ils réclament.
il y a 2 ans
Yoneda
Yoneda
2 ans
on peut avoir le même résultat avec mmap
Je ne connaissais pas
:risi_celestin:
Collector
:Michel_blanc:
il y a 2 ans
Le C est mon langage de prof préféré perso
il y a 2 ans
Yoneda
Yoneda
2 ans
le problème ce n'est pas tant malloc mais la façon dont les gens l'utilisent comme solution par défaut pour allouer de la mémoire.
Est-ce que privilégier une approche plus fonctionnelle sollicitant plus la pile serait mieux ?
Seugondaire, Duce des #hypernarboreens, Ecoutant de la #confrerie-noire.
il y a 2 ans
Est-ce que privilégier une approche plus fonctionnelle sollicitant plus la pile serait mieux ?
la pile a une taille relativement petite et a une gestion des lifetimes limitée
La meilleure façon de châtier les hommes est de toujours donner ce qu'ils réclament.
il y a 2 ans
Yoneda
Yoneda
2 ans
la pile a une taille relativement petite et a une gestion des lifetimes limitée
Alors comment faire
:risitas_hanches:
Seugondaire, Duce des #hypernarboreens, Ecoutant de la #confrerie-noire.
il y a 2 ans