162306a36Sopenharmony_ci.. include:: ../disclaimer-sp.rst 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci:Original: :ref:`Documentation/process/deprecated.rst <deprecated>` 462306a36Sopenharmony_ci:Translator: Sergio Gonzalez <sergio.collado@gmail.com> 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci.. _sp_deprecated: 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci============================================================================ 962306a36Sopenharmony_ciInterfaces obsoletos, Características del lenguaje, Atributos y Convenciones 1062306a36Sopenharmony_ci============================================================================ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ciEn un mundo perfecto, sería posible convertir todas las instancias de 1362306a36Sopenharmony_cialguna API obsoleta en una nueva API y quitar la API anterior en un 1462306a36Sopenharmony_ciúnico ciclo de desarrollo. Desafortunadamente, debido al tamaño del kernel, 1562306a36Sopenharmony_cila jerarquía de mantenimiento, y el tiempo, no siempre es posible hacer 1662306a36Sopenharmony_ciestos cambios de una única vez. Esto significa que las nuevas instancias 1762306a36Sopenharmony_cihan de ir creándose en el kernel, mientras que las antiguas se quitan, 1862306a36Sopenharmony_cihaciendo que la cantidad de trabajo para limpiar las APIs crezca. Para 1962306a36Sopenharmony_ciinformar a los desarrolladores sobre qué ha sido declarado obsoleto y por 2062306a36Sopenharmony_ciqué, ha sido creada esta lista como un lugar donde indicar cuando los usos 2162306a36Sopenharmony_ciobsoletos son propuestos para incluir en el kernel. 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci__deprecated 2462306a36Sopenharmony_ci------------ 2562306a36Sopenharmony_ciMientras que este atributo señala visualmente que un interface ha sido 2662306a36Sopenharmony_cideclarado obsoleto, este `no produce más avisos durante las compilaciones 2762306a36Sopenharmony_ci<https://git.kernel.org/linus/771c035372a036f83353eef46dbb829780330234>`_ 2862306a36Sopenharmony_ciporque uno de los objetivos del kernel es que compile sin avisos, y 2962306a36Sopenharmony_cinadie ha hecho nada para quitar estos interfaces obsoletos. Mientras 3062306a36Sopenharmony_cique usar `__deprecated` es sencillo para anotar una API obsoleta en 3162306a36Sopenharmony_ciun archivo de cabecera, no es la solución completa. Dichos interfaces 3262306a36Sopenharmony_cideben o bien ser quitados por completo, o añadidos a este archivo para 3362306a36Sopenharmony_cidesanimar a otros a usarla en el futuro. 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ciBUG() y BUG_ON() 3662306a36Sopenharmony_ci---------------- 3762306a36Sopenharmony_ciUse WARN() y WARN_ON() en su lugar, y gestione las condiciones de error 3862306a36Sopenharmony_ci"imposibles" tan elegantemente como se pueda. Mientras que la familia de 3962306a36Sopenharmony_cifunciones BUG() fueron originalmente diseñadas para actuar como una 4062306a36Sopenharmony_ci"situación imposible", confirmar y disponer de un hilo del kernel de forma 4162306a36Sopenharmony_ci"segura", estas funciones han resultado ser demasiado arriesgadas. (e.g. 4262306a36Sopenharmony_ci"¿en qué orden se necesitan liberar los locks? ¿Se han restaurado sus 4362306a36Sopenharmony_ciestados?). La popular función BUG() desestabilizará el sistema o lo romperá 4462306a36Sopenharmony_citotalmente, lo cual hace imposible depurarlo o incluso generar reportes de 4562306a36Sopenharmony_cicrash. Linus tiene una `opinión muy fuerte 4662306a36Sopenharmony_ci<https://lore.kernel.org/lkml/CA+55aFy6jNLsywVYdGp83AMrXBo_P-pkjkphPGrO=82SPKCpLQ@mail.gmail.com/>`_ 4762306a36Sopenharmony_ciy sentimientos `sobre esto 4862306a36Sopenharmony_ci<https://lore.kernel.org/lkml/CAHk-=whDHsbK3HTOpTF=ue_o04onRwTEaK_ZoJp_fjbqq4+=Jw@mail.gmail.com/>`_. 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ciNótese que la familia de funciones WARN() únicamente debería ser usada 5162306a36Sopenharmony_cien situaciones que se "esperan no sean alcanzables". Si se quiere 5262306a36Sopenharmony_ciavisar sobre situaciones "alcanzables pero no deseadas", úsese la familia 5362306a36Sopenharmony_cide funciones pr_warn(). Los responsables del sistema pueden haber definido 5462306a36Sopenharmony_ci*panic_on_warn* sysctl para asegurarse que sus sistemas no continúan 5562306a36Sopenharmony_ciejecutándose en presencia del condiciones "no alcanzables". (Por ejemplo, 5662306a36Sopenharmony_civéase commits como `este 5762306a36Sopenharmony_ci<https://git.kernel.org/linus/d4689846881d160a4d12a514e991a740bcb5d65a>`_.) 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciOperaciones aritméticas en los argumentos de reserva de memoria 6062306a36Sopenharmony_ci--------------------------------------------------------------- 6162306a36Sopenharmony_ciLos cálculos dinámicos de tamaño (especialmente multiplicaciones) no 6262306a36Sopenharmony_cideberían realizarse en los argumentos de reserva de memoria (o similares) 6362306a36Sopenharmony_cidebido al riesgo de desbordamiento. Esto puede llevar a valores rotando y 6462306a36Sopenharmony_cique se realicen reservas de memoria menores que las que se esperaban. El 6562306a36Sopenharmony_ciuso de esas reservas puede llevar a desbordamientos en el 'heap' de memoria 6662306a36Sopenharmony_ciy otros funcionamientos incorrectos. (Una excepción a esto son los valores 6762306a36Sopenharmony_ciliterales donde el compilador si puede avisar si estos puede desbordarse. 6862306a36Sopenharmony_ciDe todos modos, el método recomendado en estos caso es reescribir el código 6962306a36Sopenharmony_cicomo se sugiere a continuación para evitar las operaciones aritméticas en 7062306a36Sopenharmony_cila reserva de memoria.) 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ciPor ejemplo, no utilice `count * size`` como argumento, como en:: 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci foo = kmalloc(count * size, GFP_KERNEL); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ciEn vez de eso, utilice la reserva con dos argumentos:: 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci foo = kmalloc_array(count, size, GFP_KERNEL); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ciEspecíficamente, kmalloc() puede ser sustituido con kmalloc_array(), 8162306a36Sopenharmony_cikzalloc() puede ser sustituido con kcalloc(). 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ciSi no existen funciones con dos argumentos, utilice las funciones que se 8462306a36Sopenharmony_cisaturan, en caso de desbordamiento:: 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci bar = vmalloc(array_size(count, size)); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ciOtro caso común a evitar es calcular el tamaño de una estructura com 8962306a36Sopenharmony_cila suma de otras estructuras, como en:: 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci header = kzalloc(sizeof(*header) + count * sizeof(*header->item), 9262306a36Sopenharmony_ci GFP_KERNEL); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ciEn vez de eso emplee:: 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci header = kzalloc(struct_size(header, item, count), GFP_KERNEL); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci.. note:: Si se usa struct_size() en una estructura que contiene un elemento 9962306a36Sopenharmony_ci de longitud cero o un array de un único elemento como un array miembro, 10062306a36Sopenharmony_ci por favor reescribir ese uso y cambiar a un `miembro array flexible 10162306a36Sopenharmony_ci <#zero-length-and-one-element-arrays>`_ 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ciPara otros cálculos, por favor use las funciones de ayuda: size_mul(), 10562306a36Sopenharmony_cisize_add(), and size_sub(). Por ejemplo, en el caso de:: 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ciRe-escríbase, como:: 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci foo = krealloc(size_add(current_size, 11262306a36Sopenharmony_ci size_mul(chunk_size, 11362306a36Sopenharmony_ci size_sub(count, 3))), GFP_KERNEL); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciPara más detalles, mire también array3_size() y flex_array_size(), 11662306a36Sopenharmony_cicomo también la familia de funciones relacionadas check_mul_overflow(), 11762306a36Sopenharmony_cicheck_add_overflow(), check_sub_overflow(), y check_shl_overflow(). 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cisimple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull() 12162306a36Sopenharmony_ci---------------------------------------------------------------------- 12262306a36Sopenharmony_ciLas funciones: simple_strtol(), simple_strtoll(), simple_strtoul(), y 12362306a36Sopenharmony_cisimple_strtoull() explícitamente ignoran los desbordamientos, lo que puede 12462306a36Sopenharmony_cillevar a resultados inesperados por las funciones que las llaman. Las 12562306a36Sopenharmony_cifunciones respectivas kstrtol(), kstrtoll(), kstrtoul(), y kstrtoull() 12662306a36Sopenharmony_citienden a ser reemplazos correctos, aunque nótese que necesitarán que la 12762306a36Sopenharmony_cicadena de caracteres termine en NUL o en el carácter de línea nueva. 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistrcpy() 13162306a36Sopenharmony_ci-------- 13262306a36Sopenharmony_cistrcpy() no realiza verificaciones de los límites del buffer de destino. 13362306a36Sopenharmony_ciEsto puede resultar en desbordamientos lineals más allá del fin del buffer, 13462306a36Sopenharmony_cicausando todo tipo de errores. Mientras `CONFIG_FORTIFY_SOURCE=y` otras 13562306a36Sopenharmony_civarias opciones de compilación reducen el riesgo de usar esta función, no 13662306a36Sopenharmony_cihay ninguna buena razón para añadir nuevos usos de esta. El remplazo seguro 13762306a36Sopenharmony_cies la función strscpy(), aunque se ha de tener cuidado con cualquier caso 13862306a36Sopenharmony_cien el el valor retornado por strcpy() sea usado, ya que strscpy() no 13962306a36Sopenharmony_cidevuelve un puntero a el destino, sino el número de caracteres no nulos 14062306a36Sopenharmony_cicompilados (o el valor negativo de errno cuando se trunca la cadena de 14162306a36Sopenharmony_cicaracteres). 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistrncpy() en cadenas de caracteres terminadas en NUL 14462306a36Sopenharmony_ci---------------------------------------------------- 14562306a36Sopenharmony_ciEl uso de strncpy() no garantiza que el buffer de destino esté terminado en 14662306a36Sopenharmony_ciNUL. Esto puede causar varios errores de desbordamiento en lectura y otros 14762306a36Sopenharmony_citipos de funcionamiento erróneo debido a que falta la terminación en NUL. 14862306a36Sopenharmony_ciEsta función también termina la cadena de caracteres en NUL en el buffer de 14962306a36Sopenharmony_cidestino si la cadena de origen es más corta que el buffer de destino, lo 15062306a36Sopenharmony_cicual puede ser una penalización innecesaria para funciones usen esta 15162306a36Sopenharmony_cifunción con cadenas de caracteres que sí están terminadas en NUL. 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ciCuando se necesita que la cadena de destino sea terminada en NUL, 15462306a36Sopenharmony_ciel mejor reemplazo es usar la función strscpy(), aunque se ha de tener 15562306a36Sopenharmony_cicuidado en los casos en los que el valor de strncpy() fuera usado, ya que 15662306a36Sopenharmony_cistrscpy() no devuelve un puntero al destino, sino el número de 15762306a36Sopenharmony_cicaracteres no nulos copiados (o el valor negativo de errno cuando se trunca 15862306a36Sopenharmony_cila cadena de caracteres). Cualquier caso restante que necesitase todavía 15962306a36Sopenharmony_ciser terminado en el caracter nulo, debería usar strscpy_pad(). 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ciSi una función usa cadenas de caracteres que no necesitan terminar en NUL, 16262306a36Sopenharmony_cidebería usarse strtomem(), y el destino debería señalarse con el atributo 16362306a36Sopenharmony_ci`__nonstring 16462306a36Sopenharmony_ci<https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html>`_ 16562306a36Sopenharmony_cipara evitar avisos futuros en el compilador. Para casos que todavía 16662306a36Sopenharmony_cinecesitan cadenas de caracteres que se rellenen al final con el 16762306a36Sopenharmony_cicaracter NUL, usar strtomem_pad(). 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistrlcpy() 17062306a36Sopenharmony_ci--------- 17162306a36Sopenharmony_cistrlcpy() primero lee por completo el buffer de origen (ya que el valor 17262306a36Sopenharmony_cidevuelto intenta ser el mismo que el de strlen()). Esta lectura puede 17362306a36Sopenharmony_cisobrepasar el límite de tamaño del destino. Esto ineficiente y puede causar 17462306a36Sopenharmony_cidesbordamientos de lectura si la cadena de origen no está terminada en el 17562306a36Sopenharmony_cicarácter NUL. El reemplazo seguro de esta función es strscpy(), pero se ha 17662306a36Sopenharmony_cide tener cuidado que en los casos en lso que se usase el valor devuelto de 17762306a36Sopenharmony_cistrlcpy(), ya que strscpy() devolverá valores negativos de erno cuando se 17862306a36Sopenharmony_ciproduzcan truncados. 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ciEspecificación de formato %p 18162306a36Sopenharmony_ci---------------------------- 18262306a36Sopenharmony_ciTradicionalmente,el uso de "%p" en el formato de cadenas de caracteres 18362306a36Sopenharmony_ciresultaría en exponer esas direcciones en dmesg, proc, sysfs, etc. En vez 18462306a36Sopenharmony_cide dejar que sean una vulnerabilidad, todos los "%p" que se usan en el 18562306a36Sopenharmony_cikernel se imprimen como un hash, haciéndolos efectivamente inutilizables 18662306a36Sopenharmony_cipara usarlos como direcciones de memoria. Nuevos usos de "%p" no deberían 18762306a36Sopenharmony_ciser añadidos al kernel. Para textos de direcciones, usar "%pS" es 18862306a36Sopenharmony_cimejor, ya que resulta en el nombre del símbolo. Para prácticamente el 18962306a36Sopenharmony_ciresto de casos, mejor no usar "%p" en absoluto. 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ciParafraseando las actuales `direcciones de Linus <https://lore.kernel.org/lkml/CA+55aFwQEd_d40g4mUCSsVRZzrFPUJt74vc6PPpb675hYNXcKw@mail.gmail.com/>`_: 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci- Si el valor "hasheado" "%p" no tienen ninguna finalidad, preguntarse si el 19462306a36Sopenharmony_ci puntero es realmente importante. ¿Quizás se podría quitar totalmente? 19562306a36Sopenharmony_ci- Si realmente se piensa que el valor del puntero es importante, ¿porqué 19662306a36Sopenharmony_ci algún estado del sistema o nivel de privilegio de usuario es considerado 19762306a36Sopenharmony_ci "especial"? Si piensa que puede justificarse (en comentarios y mensajes 19862306a36Sopenharmony_ci del commit), de forma suficiente como para pasar el escrutinio de Linux, 19962306a36Sopenharmony_ci quizás pueda usar el "%p", a la vez que se asegura que tiene los permisos 20062306a36Sopenharmony_ci correspondientes. 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ciSi está depurando algo donde el "%p" hasheado está causando problemas, 20362306a36Sopenharmony_cise puede arrancar temporalmente con la opción de depuración "`no_hash_pointers 20462306a36Sopenharmony_ci<https://git.kernel.org/linus/5ead723a20e0447bc7db33dc3070b420e5f80aa6>`_". 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ciArrays de longitud variable (VLAs) 20862306a36Sopenharmony_ci---------------------------------- 20962306a36Sopenharmony_ciUsando VLA en la pila (stack) produce un código mucho peor que los arrays 21062306a36Sopenharmony_cide tamaño estático. Mientras que estos errores no triviales de `rendimiento 21162306a36Sopenharmony_ci<https://git.kernel.org/linus/02361bc77888>`_ son razón suficiente 21262306a36Sopenharmony_cipara no usar VLAs, esto además son un riesgo de seguridad. El crecimiento 21362306a36Sopenharmony_cidinámico del array en la pila, puede exceder la memoria restante en 21462306a36Sopenharmony_ciel segmento de la pila. Esto podría llevara a un fallo, posible sobre-escritura 21562306a36Sopenharmony_cide contenido al final de la pila (cuando se construye sin 21662306a36Sopenharmony_ci`CONFIG_THREAD_INFO_IN_TASK=y`), o sobre-escritura de la memoria adyacente 21762306a36Sopenharmony_cia la pila (cuando se construye sin `CONFIG_VMAP_STACK=y`). 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ciSwitch case fall-through implícito 22162306a36Sopenharmony_ci---------------------------------- 22262306a36Sopenharmony_ciEl lenguaje C permite a las sentencias 'switch' saltar de un caso al 22362306a36Sopenharmony_cisiguiente caso cuando la sentencia de ruptura "break" no aparece al final 22462306a36Sopenharmony_cidel caso. Esto, introduce ambigüedad en el código, ya que no siempre está 22562306a36Sopenharmony_ciclaro si el 'break' que falta es intencionado o un olvido. Por ejemplo, no 22662306a36Sopenharmony_cies obvio solamente mirando al código si `STATE_ONE` está escrito para 22762306a36Sopenharmony_ciintencionadamente saltar en `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_ciYa que ha habido una larga lista de defectos `debidos a declaraciones de "break" 24062306a36Sopenharmony_cique faltan <https://cwe.mitre.org/data/definitions/484.html>`_, no se 24162306a36Sopenharmony_cipermiten 'fall-through' implícitos. Para identificar 'fall-through' 24262306a36Sopenharmony_ciintencionados, se ha adoptado la pseudo-palabra-clave macro "falltrhrough", 24362306a36Sopenharmony_cique expande las extensiones de gcc `__attribute__((__fallthrough__)) 24462306a36Sopenharmony_ci<https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html>`_. 24562306a36Sopenharmony_ci(Cuando la sintaxis de C17/c18 `[[fallthrough]]` sea más comúnmente 24662306a36Sopenharmony_cisoportadas por los compiladores de C, analizadores estáticos, e IDEs, 24762306a36Sopenharmony_cise puede cambiar a usar esa sintaxis para esa pseudo-palabra-clave. 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ciTodos los bloques switch/case deben acabar en uno de: 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci* break; 25262306a36Sopenharmony_ci* fallthrough; 25362306a36Sopenharmony_ci* continue; 25462306a36Sopenharmony_ci* goto <label>; 25562306a36Sopenharmony_ci* return [expression]; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ciArrays de longitud cero y un elemento 25962306a36Sopenharmony_ci------------------------------------- 26062306a36Sopenharmony_ciHay una necesidad habitual en el kernel de proveer una forma para declarar 26162306a36Sopenharmony_ciun grupo de elementos consecutivos de tamaño dinámico en una estructura. 26262306a36Sopenharmony_ciEl código del kernel debería usar siempre `"miembros array flexible" <https://en.wikipedia.org/wiki/Flexible_array_member>`_ 26362306a36Sopenharmony_cien estos casos. El estilo anterior de arrays de un elemento o de longitud 26462306a36Sopenharmony_cicero, no deben usarse más. 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ciEn el código C más antiguo, los elementos finales de tamaño dinámico se 26762306a36Sopenharmony_ciobtenían especificando un array de un elemento al final de una estructura:: 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci struct something { 27062306a36Sopenharmony_ci size_t count; 27162306a36Sopenharmony_ci struct foo items[1]; 27262306a36Sopenharmony_ci }; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ciEn código C más antiguo, elementos seguidos de tamaño dinámico eran creados 27562306a36Sopenharmony_ciespecificando una array de un único elemento al final de una estructura:: 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci struct something { 27862306a36Sopenharmony_ci size_t count; 27962306a36Sopenharmony_ci struct foo items[1]; 28062306a36Sopenharmony_ci }; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ciEsto llevó a resultados incorrectos en los cálculos de tamaño mediante 28362306a36Sopenharmony_cisizeof() (el cual hubiera necesitado eliminar el tamaño del último elemento 28462306a36Sopenharmony_cipara tener un tamaño correcto de la "cabecera"). Una `extensión de GNU C 28562306a36Sopenharmony_ci<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_ se empezó a usar 28662306a36Sopenharmony_cipara permitir los arrays de longitud cero, para evitar estos tipos de 28762306a36Sopenharmony_ciproblemas de tamaño:: 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci struct something { 29062306a36Sopenharmony_ci size_t count; 29162306a36Sopenharmony_ci struct foo items[0]; 29262306a36Sopenharmony_ci }; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ciPero esto llevó a otros problemas, y no solucionó algunos otros problemas 29562306a36Sopenharmony_cicompartidos por ambos estilos, como no ser capaz de detectar cuando ese array 29662306a36Sopenharmony_ciaccidentalmente _no_ es usado al final de la estructura (lo que podía pasar 29762306a36Sopenharmony_cidirectamente, o cuando dicha estructura era usada en uniones, estructuras 29862306a36Sopenharmony_cide estructuras, etc). 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ciC99 introdujo "los arrays miembros flexibles", los cuales carecen de un 30162306a36Sopenharmony_citamaño numérico en su declaración del array:: 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci struct something { 30462306a36Sopenharmony_ci size_t count; 30562306a36Sopenharmony_ci struct foo items[]; 30662306a36Sopenharmony_ci }; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ciEsta es la forma en la que el kernel espera que se declaren los elementos 30962306a36Sopenharmony_cide tamaño dinámico concatenados. Esto permite al compilador generar 31062306a36Sopenharmony_cierrores, cuando el array flexible no es declarado en el último lugar de la 31162306a36Sopenharmony_ciestructura, lo que ayuda a prevenir errores en él código del tipo 31262306a36Sopenharmony_ci`comportamiento indefinido <https://git.kernel.org/linus/76497732932f15e7323dc805e8ea8dc11bb587cf>`_. 31362306a36Sopenharmony_ciEsto también permite al compilador analizar correctamente los tamaños de 31462306a36Sopenharmony_cilos arrays (via sizeof(), `CONFIG_FORTIFY_SOURCE`, y `CONFIG_UBSAN_BOUNDS`). 31562306a36Sopenharmony_ciPor ejemplo, si no hay un mecanismo que avise que el siguiente uso de 31662306a36Sopenharmony_cisizeof() en un array de longitud cero, siempre resulta en cero:: 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci struct something { 31962306a36Sopenharmony_ci size_t count; 32062306a36Sopenharmony_ci struct foo items[0]; 32162306a36Sopenharmony_ci }; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci struct something *instance; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL); 32662306a36Sopenharmony_ci instance->count = count; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci size = sizeof(instance->items) * instance->count; 32962306a36Sopenharmony_ci memcpy(instance->items, source, size); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ciEn la última línea del código anterior, ``zero`` vale ``cero``, cuando uno 33262306a36Sopenharmony_cipodría esperar que representa el tamaño total en bytes de la memoria dinámica 33362306a36Sopenharmony_cireservada para el array consecutivo ``items``. Aquí hay un par de ejemplos 33462306a36Sopenharmony_cimás sobre este tema: `link 1 33562306a36Sopenharmony_ci<https://git.kernel.org/linus/f2cd32a443da694ac4e28fbf4ac6f9d5cc63a539>`_, 33662306a36Sopenharmony_ci`link 2 33762306a36Sopenharmony_ci<https://git.kernel.org/linus/ab91c2a89f86be2898cee208d492816ec238b2cf>`_. 33862306a36Sopenharmony_ciSin embargo, los array de miembros flexibles tienen un type incompleto, y 33962306a36Sopenharmony_cino se ha de aplicar el operador sizeof()<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_, 34062306a36Sopenharmony_ciasí cualquier mal uso de dichos operadores será detectado inmediatamente en 34162306a36Sopenharmony_ciel momento de compilación. 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ciCon respecto a los arrays de un único elemento, se ha de ser consciente de 34462306a36Sopenharmony_cique dichos arrays ocupan al menos tanto espacio como un único objeto del 34562306a36Sopenharmony_citipo https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_, de ahí que 34662306a36Sopenharmony_ciestos contribuyan al tamaño de la estructura que los contiene. Esto es 34762306a36Sopenharmony_ciproclive a errores cada vez que se quiere calcular el tamaño total de la 34862306a36Sopenharmony_cimemoria dinámica para reservar una estructura que contenga un array de este 34962306a36Sopenharmony_citipo como su miembro:: 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci struct something { 35262306a36Sopenharmony_ci size_t count; 35362306a36Sopenharmony_ci struct foo items[1]; 35462306a36Sopenharmony_ci }; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci struct something *instance; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci instance = kmalloc(struct_size(instance, items, count - 1), GFP_KERNEL); 35962306a36Sopenharmony_ci instance->count = count; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci size = sizeof(instance->items) * instance->count; 36262306a36Sopenharmony_ci memcpy(instance->items, source, size); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ciEn el ejemplo anterior, hemos de recordar calcular ``count - 1``, cuando se 36562306a36Sopenharmony_ciusa la función de ayuda struct_size(), de otro modo estaríamos 36662306a36Sopenharmony_ci--desintencionadamente--reservando memoria para un ``items`` de más. La 36762306a36Sopenharmony_ciforma más clara y menos proclive a errores es implementar esto mediante el 36862306a36Sopenharmony_ciuso de `array miembro flexible`, junto con las funciones de ayuda: 36962306a36Sopenharmony_cistruct_size() y flex_array_size():: 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci struct something { 37262306a36Sopenharmony_ci size_t count; 37362306a36Sopenharmony_ci struct foo items[]; 37462306a36Sopenharmony_ci }; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci struct something *instance; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL); 37962306a36Sopenharmony_ci instance->count = count; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci memcpy(instance->items, source, flex_array_size(instance, items, instance->count)); 382