162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci.. include:: ../disclaimer-ita.rst
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci:Original: :ref:`Documentation/process/deprecated.rst <deprecated>`
662306a36Sopenharmony_ci:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci.. _it_deprecated:
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci==============================================================================
1162306a36Sopenharmony_ciInterfacce deprecate, caratteristiche del linguaggio, attributi, e convenzioni
1262306a36Sopenharmony_ci==============================================================================
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ciIn un mondo perfetto, sarebbe possibile prendere tutti gli usi di
1562306a36Sopenharmony_ciun'interfaccia deprecata e convertirli in quella nuova, e così sarebbe
1662306a36Sopenharmony_cipossibile rimuovere la vecchia interfaccia in un singolo ciclo di sviluppo.
1762306a36Sopenharmony_ciTuttavia, per via delle dimensioni del kernel, la gerarchia dei manutentori e
1862306a36Sopenharmony_cile tempistiche, non è sempre possibile fare questo tipo di conversione tutta
1962306a36Sopenharmony_ciin una volta. Questo significa che nuove istanze di una vecchia interfaccia
2062306a36Sopenharmony_cipotrebbero aggiungersi al kernel proprio quando si sta cercando di rimuoverle,
2162306a36Sopenharmony_ciaumentando così il carico di lavoro. Al fine di istruire gli sviluppatori su
2262306a36Sopenharmony_cicosa è considerato deprecato (e perché), è stata create la seguente lista a cui
2362306a36Sopenharmony_cifare riferimento quando qualcuno propone modifiche che usano cose deprecate.
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci__deprecated
2662306a36Sopenharmony_ci------------
2762306a36Sopenharmony_ciNonostante questo attributo marchi visibilmente un interfaccia come deprecata,
2862306a36Sopenharmony_ci`non produce più alcun avviso durante la compilazione
2962306a36Sopenharmony_ci<https://git.kernel.org/linus/771c035372a036f83353eef46dbb829780330234>`_
3062306a36Sopenharmony_ciperché uno degli obiettivi del kernel è quello di compilare senza avvisi;
3162306a36Sopenharmony_ciinoltre, nessuno stava agendo per rimuovere queste interfacce. Nonostante l'uso
3262306a36Sopenharmony_cidi `__deprecated` in un file d'intestazione sia opportuno per segnare una
3362306a36Sopenharmony_ciinterfaccia come 'vecchia', questa non è una soluzione completa. L'interfaccia
3462306a36Sopenharmony_cideve essere rimossa dal kernel, o aggiunta a questo documento per scoraggiarne
3562306a36Sopenharmony_cil'uso.
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ciBUG() e BUG_ON()
3862306a36Sopenharmony_ci----------------
3962306a36Sopenharmony_ciAl loro posto usate WARN() e WARN_ON() per gestire le
4062306a36Sopenharmony_cicondizioni "impossibili" e gestitele come se fosse possibile farlo.
4162306a36Sopenharmony_ciNonostante le funzioni della famiglia BUG() siano state progettate
4262306a36Sopenharmony_ciper asserire "situazioni impossibili" e interrompere in sicurezza un
4362306a36Sopenharmony_cithread del kernel, queste si sono rivelate essere troppo rischiose
4462306a36Sopenharmony_ci(per esempio, in quale ordine rilasciare i *lock*? Ci sono stati che
4562306a36Sopenharmony_cisono stati ripristinati?). Molto spesso l'uso di BUG()
4662306a36Sopenharmony_cidestabilizza il sistema o lo corrompe del tutto, il che rende
4762306a36Sopenharmony_ciimpossibile un'attività di debug o anche solo leggere un rapporto
4862306a36Sopenharmony_cicirca l'errore.  Linus ha un'opinione molto critica al riguardo:
4962306a36Sopenharmony_ci`email 1
5062306a36Sopenharmony_ci<https://lore.kernel.org/lkml/CA+55aFy6jNLsywVYdGp83AMrXBo_P-pkjkphPGrO=82SPKCpLQ@mail.gmail.com/>`_,
5162306a36Sopenharmony_ci`email 2
5262306a36Sopenharmony_ci<https://lore.kernel.org/lkml/CAHk-=whDHsbK3HTOpTF=ue_o04onRwTEaK_ZoJp_fjbqq4+=Jw@mail.gmail.com/>`_
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ciTenete presente che la famiglia di funzioni WARN() dovrebbe essere
5562306a36Sopenharmony_ciusato solo per situazioni che si suppone siano "impossibili".  Se
5662306a36Sopenharmony_civolete avvisare gli utenti riguardo a qualcosa di possibile anche se
5762306a36Sopenharmony_ciindesiderato, usare le funzioni della famiglia pr_warn().  Chi
5862306a36Sopenharmony_ciamministra il sistema potrebbe aver attivato l'opzione sysctl
5962306a36Sopenharmony_ci*panic_on_warn* per essere sicuri che il sistema smetta di funzionare
6062306a36Sopenharmony_ciin caso si verifichino delle condizioni "inaspettate". (per esempio,
6162306a36Sopenharmony_cidate un'occhiata al questo `commit
6262306a36Sopenharmony_ci<https://git.kernel.org/linus/d4689846881d160a4d12a514e991a740bcb5d65a>`_)
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ciCalcoli codificati negli argomenti di un allocatore
6562306a36Sopenharmony_ci----------------------------------------------------
6662306a36Sopenharmony_ciIl calcolo dinamico delle dimensioni (specialmente le moltiplicazioni) non
6762306a36Sopenharmony_cidovrebbero essere fatto negli argomenti di funzioni di allocazione di memoria
6862306a36Sopenharmony_ci(o simili) per via del rischio di overflow. Questo può portare a valori più
6962306a36Sopenharmony_cipiccoli di quelli che il chiamante si aspettava. L'uso di questo modo di
7062306a36Sopenharmony_ciallocare può portare ad un overflow della memoria di heap e altri
7162306a36Sopenharmony_cimalfunzionamenti. (Si fa eccezione per valori numerici per i quali il
7262306a36Sopenharmony_cicompilatore può generare avvisi circa un potenziale overflow. Tuttavia, anche in
7362306a36Sopenharmony_ciquesti casi è preferibile riscrivere il codice come suggerito di seguito).
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ciPer esempio, non usate ``count * size`` come argomento::
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	foo = kmalloc(count * size, GFP_KERNEL);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ciAl suo posto, si dovrebbe usare l'allocatore a due argomenti::
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	foo = kmalloc_array(count, size, GFP_KERNEL);
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ciNello specifico, kmalloc() può essere sostituta da kmalloc_array(), e kzalloc()
8462306a36Sopenharmony_cida kcalloc().
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ciSe questo tipo di allocatore non è disponibile, allora dovrebbero essere usate
8762306a36Sopenharmony_cile funzioni del tipo *saturate-on-overflow*::
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	bar = vmalloc(array_size(count, size));
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ciUn altro tipico caso da evitare è quello di calcolare la dimensione di una
9262306a36Sopenharmony_cistruttura seguita da un vettore di altre strutture, come nel seguente caso::
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	header = kzalloc(sizeof(*header) + count * sizeof(*header->item),
9562306a36Sopenharmony_ci			 GFP_KERNEL);
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ciInvece, usate la seguente funzione::
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	header = kzalloc(struct_size(header, item, count), GFP_KERNEL);
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci.. note:: Se per caso state usando struct_size() su una struttura dati che
10262306a36Sopenharmony_ci	  in coda contiene un array di lunghezza zero o uno, allora siete
10362306a36Sopenharmony_ci	  invitati a riorganizzare il vostro codice usando il
10462306a36Sopenharmony_ci	  `flexible array member <#zero-length-and-one-element-arrays>`_.
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ciPer altri calcoli, usate le funzioni size_mul(), size_add(), e size_sub(). Per
10762306a36Sopenharmony_ciesempio, al posto di::
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci       foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cidovreste scrivere:
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci       foo = krealloc(size_add(current_size,
11462306a36Sopenharmony_ci                               size_mul(chunk_size,
11562306a36Sopenharmony_ci                                        size_sub(count, 3))), GFP_KERNEL);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ciPer maggiori dettagli fate riferimento a array3_size() e flex_array_size(), ma
11862306a36Sopenharmony_cianche le funzioni della famiglia check_mul_overflow(), check_add_overflow(),
11962306a36Sopenharmony_cicheck_sub_overflow(), e check_shl_overflow().
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cisimple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull()
12262306a36Sopenharmony_ci----------------------------------------------------------------------
12362306a36Sopenharmony_ciLe funzioni simple_strtol(), simple_strtoll(),
12462306a36Sopenharmony_cisimple_strtoul(), e simple_strtoull() ignorano volutamente
12562306a36Sopenharmony_cii possibili overflow, e questo può portare il chiamante a generare risultati
12662306a36Sopenharmony_ciinaspettati. Le rispettive funzioni kstrtol(), kstrtoll(),
12762306a36Sopenharmony_cikstrtoul(), e kstrtoull() sono da considerarsi le corrette
12862306a36Sopenharmony_cisostitute; tuttavia va notato che queste richiedono che la stringa sia
12962306a36Sopenharmony_citerminata con il carattere NUL o quello di nuova riga.
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistrcpy()
13262306a36Sopenharmony_ci--------
13362306a36Sopenharmony_ciLa funzione strcpy() non fa controlli agli estremi del buffer
13462306a36Sopenharmony_cidi destinazione. Questo può portare ad un overflow oltre i limiti del
13562306a36Sopenharmony_cibuffer e generare svariati tipi di malfunzionamenti. Nonostante l'opzione
13662306a36Sopenharmony_ci`CONFIG_FORTIFY_SOURCE=y` e svariate opzioni del compilatore aiutano
13762306a36Sopenharmony_cia ridurne il rischio, non c'è alcuna buona ragione per continuare ad usare
13862306a36Sopenharmony_ciquesta funzione. La versione sicura da usare è strscpy(), tuttavia va
13962306a36Sopenharmony_ciprestata attenzione a tutti quei casi dove viene usato il valore di
14062306a36Sopenharmony_ciritorno di strcpy().  La funzione strscpy() non ritorna un puntatore
14162306a36Sopenharmony_cialla destinazione, ma un contatore dei byte non NUL copiati (oppure
14262306a36Sopenharmony_ciun errno negativo se la stringa è stata troncata).
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistrncpy() su stringe terminate con NUL
14562306a36Sopenharmony_ci--------------------------------------
14662306a36Sopenharmony_ciL'utilizzo di strncpy() non fornisce alcuna garanzia sul fatto che
14762306a36Sopenharmony_ciil buffer di destinazione verrà terminato con il carattere NUL. Questo
14862306a36Sopenharmony_cipotrebbe portare a diversi overflow di lettura o altri malfunzionamenti
14962306a36Sopenharmony_cicausati, appunto, dalla mancanza del terminatore. Questa estende la
15062306a36Sopenharmony_citerminazione nel buffer di destinazione quando la stringa d'origine è più
15162306a36Sopenharmony_cicorta; questo potrebbe portare ad una penalizzazione delle prestazioni per
15262306a36Sopenharmony_cichi usa solo stringe terminate. La versione sicura da usare è
15362306a36Sopenharmony_cistrscpy(), tuttavia va prestata attenzione a tutti quei casi dove
15462306a36Sopenharmony_civiene usato il valore di ritorno di strncpy().  La funzione strscpy()
15562306a36Sopenharmony_cinon ritorna un puntatore alla destinazione, ma un contatore dei byte
15662306a36Sopenharmony_cinon NUL copiati (oppure un errno negativo se la stringa è stata
15762306a36Sopenharmony_citroncata). Tutti i casi che necessitano di estendere la
15862306a36Sopenharmony_citerminazione con NUL dovrebbero usare strscpy_pad().
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ciSe il chiamate no usa stringhe terminate con NUL, allore strncpy()
16162306a36Sopenharmony_cipuò continuare ad essere usata, ma i buffer di destinazione devono essere
16262306a36Sopenharmony_cimarchiati con l'attributo `__nonstring <https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html>`_
16362306a36Sopenharmony_ciper evitare avvisi durante la compilazione.
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistrlcpy()
16662306a36Sopenharmony_ci---------
16762306a36Sopenharmony_ciLa funzione strlcpy(), per prima cosa, legge interamente il buffer di
16862306a36Sopenharmony_ciorigine, magari leggendo più di quanto verrà effettivamente copiato. Questo
16962306a36Sopenharmony_ciè inefficiente e può portare a overflow di lettura quando la stringa non è
17062306a36Sopenharmony_citerminata con NUL. La versione sicura da usare è strscpy(), tuttavia
17162306a36Sopenharmony_civa prestata attenzione a tutti quei casi dove viene usato il valore di
17262306a36Sopenharmony_ciritorno di strlcpy(), dato che strscpy() ritorna un valore di errno
17362306a36Sopenharmony_cinegativo quanto la stringa viene troncata.
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ciSegnaposto %p nella stringa di formato
17662306a36Sopenharmony_ci--------------------------------------
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ciTradizionalmente, l'uso del segnaposto "%p" nella stringa di formato
17962306a36Sopenharmony_ciesponne un indirizzo di memoria in dmesg, proc, sysfs, eccetera.  Per
18062306a36Sopenharmony_cievitare che questi indirizzi vengano sfruttati da malintenzionati,
18162306a36Sopenharmony_citutto gli usi di "%p" nel kernel rappresentano l'hash dell'indirizzo,
18262306a36Sopenharmony_cirendendolo di fatto inutilizzabile.  Nuovi usi di "%p" non dovrebbero
18362306a36Sopenharmony_ciessere aggiunti al kernel.  Per una rappresentazione testuale di un
18462306a36Sopenharmony_ciindirizzo usate "%pS", l'output è migliore perché mostrerà il nome del
18562306a36Sopenharmony_cisimbolo.  Per tutto il resto, semplicemente non usate "%p".
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ciParafrasando la `guida
18862306a36Sopenharmony_ci<https://lore.kernel.org/lkml/CA+55aFwQEd_d40g4mUCSsVRZzrFPUJt74vc6PPpb675hYNXcKw@mail.gmail.com/>`_
18962306a36Sopenharmony_cidi Linus:
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci- Se il valore hash di "%p" è inutile, chiediti se il puntatore stesso
19262306a36Sopenharmony_ci  è importante. Forse dovrebbe essere rimosso del tutto?
19362306a36Sopenharmony_ci- Se credi davvero che il vero valore del puntatore sia importante,
19462306a36Sopenharmony_ci  perché alcuni stati del sistema o i livelli di privilegi di un
19562306a36Sopenharmony_ci  utente sono considerati "special"? Se pensi di poterlo giustificare
19662306a36Sopenharmony_ci  (in un commento e nel messaggio del commit) abbastanza bene da
19762306a36Sopenharmony_ci  affrontare il giudizio di Linus, allora forse potrai usare "%px",
19862306a36Sopenharmony_ci  assicurandosi anche di averne il permesso.
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ciPotete disabilitare temporaneamente l'hashing di "%p" nel caso in cui questa
20162306a36Sopenharmony_cifunzionalità vi sia d'ostacolo durante una sessione di debug. Per farlo
20262306a36Sopenharmony_ciaggiungete l'opzione di debug "`no_hash_pointers
20362306a36Sopenharmony_ci<https://git.kernel.org/linus/5ead723a20e0447bc7db33dc3070b420e5f80aa6>`_" alla
20462306a36Sopenharmony_ciriga di comando del kernel.
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ciVettori a dimensione variabile (VLA)
20762306a36Sopenharmony_ci------------------------------------
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ciUsare VLA sullo stack produce codice molto peggiore rispetto a quando si usano
21062306a36Sopenharmony_civettori a dimensione fissa. Questi `problemi di prestazioni <https://git.kernel.org/linus/02361bc77888>`_,
21162306a36Sopenharmony_citutt'altro che banali, sono già un motivo valido per eliminare i VLA; in
21262306a36Sopenharmony_ciaggiunta sono anche un problema per la sicurezza. La crescita dinamica di un
21362306a36Sopenharmony_civettore nello stack potrebbe eccedere la memoria rimanente in tale segmento.
21462306a36Sopenharmony_ciQuesto può portare a dei malfunzionamenti, potrebbe sovrascrivere
21562306a36Sopenharmony_cidati importanti alla fine dello stack (quando il kernel è compilato senza
21662306a36Sopenharmony_ci`CONFIG_THREAD_INFO_IN_TASK=y`), o sovrascrivere un pezzo di memoria adiacente
21762306a36Sopenharmony_ciallo stack (quando il kernel è compilato senza `CONFIG_VMAP_STACK=y`).
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ciSalto implicito nell'istruzione switch-case
22062306a36Sopenharmony_ci-------------------------------------------
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ciIl linguaggio C permette ai casi di un'istruzione `switch` di saltare al
22362306a36Sopenharmony_ciprossimo caso quando l'istruzione "break" viene omessa alla fine del caso
22462306a36Sopenharmony_cicorrente. Tuttavia questo rende il codice ambiguo perché non è sempre ovvio se
22562306a36Sopenharmony_cil'istruzione "break" viene omessa intenzionalmente o è un baco. Per esempio,
22662306a36Sopenharmony_ciosservando il seguente pezzo di codice non è chiaro se lo stato
22762306a36Sopenharmony_ci`STATE_ONE` è stato progettato apposta per eseguire anche `STATE_TWO`::
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci  switch (value) {
23062306a36Sopenharmony_ci  case STATE_ONE:
23162306a36Sopenharmony_ci          do_something();
23262306a36Sopenharmony_ci  case STATE_TWO:
23362306a36Sopenharmony_ci          do_other();
23462306a36Sopenharmony_ci          break;
23562306a36Sopenharmony_ci  default:
23662306a36Sopenharmony_ci          WARN("unknown state");
23762306a36Sopenharmony_ci  }
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ciDato che c'è stata una lunga lista di problemi `dovuti alla mancanza dell'istruzione
24062306a36Sopenharmony_ci"break" <https://cwe.mitre.org/data/definitions/484.html>`_, oggigiorno non
24162306a36Sopenharmony_cipermettiamo più che vi sia un "salto implicito" (*fall-through*). Per
24262306a36Sopenharmony_ciidentificare un salto implicito intenzionale abbiamo adottato la pseudo
24362306a36Sopenharmony_ciparola chiave 'fallthrough' che viene espansa nell'estensione di gcc
24462306a36Sopenharmony_ci`__attribute__((fallthrough))` `Statement Attributes
24562306a36Sopenharmony_ci<https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html>`_.
24662306a36Sopenharmony_ci(Quando la sintassi C17/C18 `[[fallthrough]]` sarà più comunemente
24762306a36Sopenharmony_cisupportata dai compilatori C, analizzatori statici, e dagli IDE,
24862306a36Sopenharmony_ciallora potremo usare quella sintassi per la pseudo parola chiave)
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ciQuando la sintassi [[fallthrough]] sarà più comunemente supportata dai
25162306a36Sopenharmony_cicompilatori, analizzatori statici, e ambienti di sviluppo IDE,
25262306a36Sopenharmony_ciallora potremo usarla anche noi.
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ciNe consegue che tutti i blocchi switch/case devono finire in uno dei seguenti
25562306a36Sopenharmony_cimodi:
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci* ``break;``
25862306a36Sopenharmony_ci* `fallthrough;``
25962306a36Sopenharmony_ci* ``continue;``
26062306a36Sopenharmony_ci* ``goto <label>;``
26162306a36Sopenharmony_ci* ``return [expression];``
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ciArray di lunghezza zero o con un solo elemento
26462306a36Sopenharmony_ci----------------------------------------------
26562306a36Sopenharmony_ciAll'interno del kernel ricorre spesso la necessita di avere membri
26662306a36Sopenharmony_cidi dimensione variabile all'interno di una struttura dati. In questi
26762306a36Sopenharmony_cicasi il codice del kernel dovrebbe usare sempre i `"flexible array
26862306a36Sopenharmony_cimember" <https://en.wikipedia.org/wiki/Flexible_array_member>`_. La
26962306a36Sopenharmony_citecnica degli array a lunghezza nulla o di un solo elemento non
27062306a36Sopenharmony_cidovrebbe essere più usata.
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ciNel codice C più vecchio, la dichiarazione di un membro di dimensione
27362306a36Sopenharmony_civariabile in coda ad una struttura dati veniva fatto dichiarando un
27462306a36Sopenharmony_ciarray di un solo elemento posizionato alla fine della struttura dati::
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci        struct something {
27762306a36Sopenharmony_ci                size_t count;
27862306a36Sopenharmony_ci                struct foo items[1];
27962306a36Sopenharmony_ci        };
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ciQuesto ha portato ad un calcolo di sizeof() traballante (dovrebbe
28262306a36Sopenharmony_cirimuovere la dimensione del singolo elemento in coda per calcolare la
28362306a36Sopenharmony_cidimensione esatta dell' "intestazione"). Per evitare questi problemi è
28462306a36Sopenharmony_cistata introdotta un' `estensione a GNU C
28562306a36Sopenharmony_ci<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_ che
28662306a36Sopenharmony_cipermettesse la dichiarazione di array a lungezza zero::
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci        struct something {
28962306a36Sopenharmony_ci                size_t count;
29062306a36Sopenharmony_ci                struct foo items[0];
29162306a36Sopenharmony_ci        };
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ciMa questo ha portato nuovi problemi, e non ha risolto alcuni dei
29462306a36Sopenharmony_ciproblemi che affliggono entrambe le tecniche: per esempio
29562306a36Sopenharmony_cil'impossibilità di riconoscere se un array di quel tipo viene usato
29662306a36Sopenharmony_cinel mezzo di una struttura dati e _non_ alla fine (potrebbe accadere
29762306a36Sopenharmony_cisia direttamente, sia indirettamente quando si usano le unioni o le
29862306a36Sopenharmony_cistrutture di strutture).
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ciLo standard C99 introduce i "flexible array members". Questi array non
30162306a36Sopenharmony_cihanno una dimensione nella loro dichiarazione::
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci        struct something {
30462306a36Sopenharmony_ci                size_t count;
30562306a36Sopenharmony_ci                struct foo items[];
30662306a36Sopenharmony_ci        };
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ciQuesto è il modo con cui ci si aspetta che vengano dichiarati gli
30962306a36Sopenharmony_cielementi di lunghezza variabile in coda alle strutture dati.  Permette
31062306a36Sopenharmony_cial compilatore di produrre errori quando gli array flessibili non si
31162306a36Sopenharmony_citrovano alla fine della struttura dati, il che permette di prevenire
31262306a36Sopenharmony_cialcuni tipi di bachi dovuti a `comportamenti inaspettati
31362306a36Sopenharmony_ci<https://git.kernel.org/linus/76497732932f15e7323dc805e8ea8dc11bb587cf>`_.
31462306a36Sopenharmony_ciInoltre, permette al compilatore di analizzare correttamente le
31562306a36Sopenharmony_cidimensioni degli array (attraverso sizeof(), `CONFIG_FORTIFY_SOURCE`,
31662306a36Sopenharmony_cie `CONFIG_UBSAN_BOUNDS`). Per esempio, non esiste alcun meccanismo in
31762306a36Sopenharmony_cigrado di avvisarci che il seguente uso di sizeof() dia sempre come
31862306a36Sopenharmony_cizero come risultato::
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci        struct something {
32162306a36Sopenharmony_ci                size_t count;
32262306a36Sopenharmony_ci                struct foo items[0];
32362306a36Sopenharmony_ci        };
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci        struct something *instance;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci        instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL);
32862306a36Sopenharmony_ci        instance->count = count;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci        size = sizeof(instance->items) * instance->count;
33162306a36Sopenharmony_ci        memcpy(instance->items, source, size);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ciIl valore di ``size`` nell'ultima riga sarà ``zero``, quando uno
33462306a36Sopenharmony_ciinvece si aspetterebbe che il suo valore sia la dimensione totale in
33562306a36Sopenharmony_cibyte dell'allocazione dinamica che abbiamo appena fatto per l'array
33662306a36Sopenharmony_ci``items``. Qui un paio di esempi reali del problema: `collegamento 1
33762306a36Sopenharmony_ci<https://git.kernel.org/linus/f2cd32a443da694ac4e28fbf4ac6f9d5cc63a539>`_,
33862306a36Sopenharmony_ci`collegamento 2
33962306a36Sopenharmony_ci<https://git.kernel.org/linus/ab91c2a89f86be2898cee208d492816ec238b2cf>`_.
34062306a36Sopenharmony_ciInvece, `i flexible array members hanno un tipo incompleto, e quindi
34162306a36Sopenharmony_cisizeof() non può essere applicato
34262306a36Sopenharmony_ci<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_; dunque ogni
34362306a36Sopenharmony_ciuso scorretto di questo operatore verrà identificato immediatamente
34462306a36Sopenharmony_cidurante la compilazione.
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ciPer quanto riguarda gli array di un solo elemento, bisogna essere
34762306a36Sopenharmony_ciconsapevoli che `questi array occupano almeno quanto lo spazio di un
34862306a36Sopenharmony_cisingolo oggetti dello stesso tipo
34962306a36Sopenharmony_ci<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_, e quindi
35062306a36Sopenharmony_cicontribuiscono al calcolo della dimensione della struttura che li
35162306a36Sopenharmony_cicontiene. In questo caso è facile commettere errori quando si vuole
35262306a36Sopenharmony_cicalcolare la dimensione totale della memoria totale da allocare per
35362306a36Sopenharmony_ciuna struttura dati::
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci        struct something {
35662306a36Sopenharmony_ci                size_t count;
35762306a36Sopenharmony_ci                struct foo items[1];
35862306a36Sopenharmony_ci        };
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci        struct something *instance;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci        instance = kmalloc(struct_size(instance, items, count - 1), GFP_KERNEL);
36362306a36Sopenharmony_ci        instance->count = count;
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci        size = sizeof(instance->items) * instance->count;
36662306a36Sopenharmony_ci        memcpy(instance->items, source, size);
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ciIn questo esempio ci siamo dovuti ricordare di usare ``count - 1`` in
36962306a36Sopenharmony_cistruct_size(), altrimenti avremmo --inavvertitamente-- allocato
37062306a36Sopenharmony_cimemoria per un oggetti ``items`` in più. Il modo più pulito e meno
37162306a36Sopenharmony_cipropenso agli errori è quello di usare i `flexible array member`, in
37262306a36Sopenharmony_cicombinazione con struct_size() e flex_array_size()::
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci        struct something {
37562306a36Sopenharmony_ci                size_t count;
37662306a36Sopenharmony_ci                struct foo items[];
37762306a36Sopenharmony_ci        };
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci        struct something *instance;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci        instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL);
38262306a36Sopenharmony_ci        instance->count = count;
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci        memcpy(instance->items, source, flex_array_size(instance, items, instance->count));
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ciCi sono due casi speciali dove è necessario usare la macro DECLARE_FLEX_ARRAY()
38762306a36Sopenharmony_ci(da notare che la stessa macro è chiamata __DECLARE_FLEX_ARRAY() nei file di
38862306a36Sopenharmony_ciintestazione UAPI). Uno è quando l'array flessibile è l'unico elemento di una
38962306a36Sopenharmony_cistruttura, e l'altro quando è parte di un unione. Per motivi non tecnici, entrambi
39062306a36Sopenharmony_cii casi d'uso non sono permessi dalla specifica C99. Per esempio, per
39162306a36Sopenharmony_ciconvertire il seguente codice::
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci    struct something {
39462306a36Sopenharmony_ci        ...
39562306a36Sopenharmony_ci        union {
39662306a36Sopenharmony_ci            struct type1 one[0];
39762306a36Sopenharmony_ci            struct type2 two[0];
39862306a36Sopenharmony_ci        };
39962306a36Sopenharmony_ci    };
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ciLa macro di supporto dev'essere usata::
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci    struct something {
40462306a36Sopenharmony_ci        ...
40562306a36Sopenharmony_ci        union {
40662306a36Sopenharmony_ci            DECLARE_FLEX_ARRAY(struct type1, one);
40762306a36Sopenharmony_ci            DECLARE_FLEX_ARRAY(struct type2, two);
40862306a36Sopenharmony_ci        };
40962306a36Sopenharmony_ci    };
410