En langage C, lorsque vous passez une structure à une fonction par valeur, une copie complète de la structure est créée dans une zone de mémoire temporaire (généralement sur la pile de la fonction). Cela signifie que toute modification à l'intérieur de la fonction n'affectera pas l'instance originale de la structure à l'extérieur de la fonction.
Lorsque vous passez de grandes structures par valeur, vous êtes confronté à des coûts en temps et en mémoire en raison de la nécessité de copier tous les membres de la structure. Par conséquent, la pratique standard consiste à passer un pointeur vers la structure :
#include <stdio.h> struct Data { int arr[1000]; int flag; }; void modify_by_value(struct Data d) { d.flag = 10; // Ne modifiera que la copie locale } void modify_by_pointer(struct Data *d) { d->flag = 20; // Modifiera l'original } int main() { struct Data data = { {0}, 0 }; modify_by_value(data); // data.flag == 0 modify_by_pointer(&data); // data.flag == 20 return 0; }
Avantages du passage par pointeur :
Inconvénients du passage par valeur :
Que se passe-t-il si la fonction retourne une structure par valeur ? Quels sont les risques ?
Réponse :
En C, il est possible de retourner une structure par valeur d'une fonction, par exemple :
struct Point { int x, y; }; struct Point make_point(int x, int y) { struct Point p = {x, y}; return p; // une copie est retournée }
Le principal risque est la performance : une copie de la structure est créée et retournée. De plus, en cas de retour erroné de l'adresse d'une variable locale, la structure peut pointer vers une mémoire invalide :
struct Point* bad() { struct Point p = {1, 2}; return &p; // erreur : retour de l'adresse d'une variable locale }
Histoire
Sur des dispositifs embarqués avec peu de pile, un développeur a passé une grande structure (1 Ko) par valeur, entraînant un débordement de pile et des défaillances sporadiques du système. L'enquête a révélé que la copie de chaque structure entraînait un manque de mémoire de pile lors d'un profond enchaînement d'appels.
Histoire
Dans un système serveur d'entreprise, un programmeur a retourné un pointeur vers une structure locale, et dans le code, des accès à des pointeurs "flottants" se produisaient après la sortie de la fonction. Cela a entraîné un segfault critique en production avec une reproduction rare.
Histoire
Dans un projet open source, la performance a chuté après le passage à une fonction retournant une structure complexe par valeur avec des tableaux internes. Le profileur a révélé le coût en temps processeur dû à des copies multiples inutiles de structures.