Obtén la respuesta incorrecta——sobre un número incierto de variables.
Cuando ejecuté el programa a continuación en el sistema Linux, no pude obtener la respuesta esperada “9”. Pero puedo obtenerla en el sistema Windows.
¿Por qué sucede esto?
#include <stdio.h>
int sum(int num, ...) {
int* p = &num + 1;
int res = 0;
while (num--) {
res += *p++;
}
return res;
}
int main() {
printf("%d\n", sum(3, 2, 3, 4));
return 0;
}
Lo depuré en GDB, se muestra a continuación:
imagen de descripción de la imagen
La configuración de mi sistema es la siguiente.
Versión de Linux 5.11.0-41-generic (buildd@lgw01-amd64-005) (gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0, GNU ld (GNU Binutils para Ubuntu) 2.34)</stdio.h>
davy.ai
El problema está relacionado con la forma en que se pasan los argumentos en los sistemas Linux y Windows. En el lenguaje C, las funciones variádicas se implementan utilizando la sintaxis de “puntos suspensivos”, que permite que una función acepte un número variable de argumentos.
En este programa en particular, la función variádica
sum
toma un enteronum
seguido de una secuencia de enteros. La funciónsum
utiliza aritmética de punteros para iterar sobre la secuencia de enteros y calcular su suma.El problema con el código es que asume que los argumentos pasados a la función
sum
se almacenan en ubicaciones de memoria consecutivas. Esto no está garantizado por el estándar C y puede variar entre diferentes sistemas y compiladores.En el sistema Windows, los argumentos resultan estar pasados en ubicaciones de memoria consecutivas, lo que permite que el programa funcione correctamente. Sin embargo, en el sistema Linux, los argumentos se pasan en un orden diferente o utilizando una disposición de memoria diferente, lo que hace que el programa se comporte incorrectamente.
Para solucionar este problema, puedes modificar la función
sum
para utilizar un enfoque diferente para iterar sobre los argumentos. Una técnica común es utilizar las macrosva_start
,va_arg
yva_end
de la bibliotecastdarg.h
para acceder a los argumentos variables de manera portátil y segura. Aquí tienes una implementación de ejemplo de la funciónsum
utilizandova_list
:Esta versión de la función
sum
utilizava_list
para inicializar, iterar y limpiar los argumentos variables pasados a la función. Es más robusta y debería funcionar correctamente en diferentes sistemas y compiladores.</stdarg.h>