
Roberto S. Barnes
Ahora, antes de que las personas comiencen a marcar esto como un dup, he leído todo lo siguiente, ninguno de los cuales proporciona la respuesta que estoy buscando:
- C Preguntas frecuentes: ¿Qué hay de malo en convertir el valor de retorno de malloc?
- SO: ¿Debería emitir explícitamente el valor de retorno de malloc()?
- SO: punteros innecesarios en C
- SO: ¿Lanzo el resultado de malloc?
Tanto las preguntas frecuentes de C como muchas respuestas a las preguntas anteriores citan un error misterioso que malloc
El valor de retorno de puede ocultar; sin embargo, ninguno de ellos da un ejemplo específico de tal error en la práctica. Ahora presta atención a lo que dije errorno advertencia.
Ahora dado el siguiente código:
#include <string.h>
#include <stdio.h>
// #include <stdlib.h>
int main(int argc, char** argv) {
char * p = /*(char*)*/malloc(10);
strcpy(p, "hello");
printf("%s\n", p);
return 0;
}
La compilación del código anterior con gcc 4.2, con y sin cast da las mismas advertencias, y el programa se ejecuta correctamente y proporciona los mismos resultados en ambos casos.
anon@anon:~/$ gcc -Wextra nostdlib_malloc.c -o nostdlib_malloc
nostdlib_malloc.c: In function ‘main’:
nostdlib_malloc.c:7: warning: incompatible implicit declaration of built-in function ‘malloc’
anon@anon:~/$ ./nostdlib_malloc
hello
Entonces, ¿alguien puede dar un ejemplo de código específico de un error de compilación o tiempo de ejecución que podría ocurrir debido a la conversión? malloc
valor de retorno de, o es sólo una leyenda urbana?
Editar Me he encontrado con dos argumentos bien escritos con respecto a este tema:
- A favor de Casting: Asesoría CERT: Transmitir inmediatamente el resultado de una llamada de función de asignación de memoria en un puntero al tipo asignado
- Contra Casting (Error 404 a partir del 2012-02-14: use el Archivo de Internet Wayback Machine copia de 2010-01-27. {2016-03-18:”La página no se puede rastrear ni mostrar debido a robots.txt.”})

Hormiga
Uno de los buenos argumentos de alto nivel en contra de lanzar el resultado de malloc
a menudo no se menciona, aunque, en mi opinión, es más importante que los problemas conocidos de nivel inferior (como truncar el puntero cuando falta la declaración).
Una buena práctica de programación es escribir código, que sea lo más independiente posible del tipo. Esto significa, en particular, que los nombres de tipo deben mencionarse en el código lo menos posible o, mejor, no mencionarse en absoluto. Esto se aplica a las conversiones (evitar conversiones innecesarias), tipos como argumentos de sizeof
(evite usar nombres de tipo en sizeof
) y, en general, todas las demás referencias a nombres de tipos.
Los nombres de tipos pertenecen a las declaraciones. En la medida de lo posible, los nombres de tipo deben restringirse a declaraciones y solo a declaraciones.
Desde este punto de vista, este fragmento de código es malo.
int *p;
...
p = (int*) malloc(n * sizeof(int));
y esto es mucho mejor
int *p;
...
p = malloc(n * sizeof *p);
no simplemente porque “no arroja el resultado de malloc
“, sino porque es independiente del tipo (o independiente del tipo, si lo prefiere), porque se ajusta automáticamente a cualquier tipo p
se declara con, sin requerir ninguna intervención por parte del usuario.

peter joot
Si hace esto al compilar en modo de 64 bits, su puntero devuelto se truncará a 32 bits.
EDITAR: Perdón por ser demasiado breve. Aquí hay un fragmento de código de ejemplo para fines de discusión.
main()
{
char * c = (char *)malloc(2) ;
printf("%p", c) ;
}
Suponga que el puntero del montón devuelto es algo más grande que lo que se puede representar en un int, digamos 0xAB00000000.
Si malloc no está prototipado para devolver un puntero, el valor int devuelto estará inicialmente en algún registro con todos los bits significativos establecidos. Ahora el compilador dice: “Está bien, ¿cómo convierto e int en un puntero?”. Será una extensión de signo o una extensión cero de los 32 bits de bajo orden que se le ha dicho a malloc que “devuelve” al omitir el prototipo. Dado que int está firmado, creo que la conversión será una extensión de signo, que en este caso convertirá el valor a cero. Con un valor de retorno de 0xABF0000000, obtendrá un puntero distinto de cero que también causará algo de diversión cuando intente desreferenciarlo.

Prueba
Una regla de software reutilizable:
En el caso de escribir una función en línea en la que se usó malloc(), para que también sea reutilizable para el código C++, realice una conversión de tipos explícita (por ejemplo, (char*)); de lo contrario, el compilador se quejará.

Yogeesh HT
Un puntero vacío en C se puede asignar a cualquier puntero sin una conversión explícita. El compilador dará una advertencia, pero puede ser reutilizable en C++ por tipo de fundición malloc()
al tipo correspondiente. Sin tipo de fundición también se puede utilizar en Cporque C no es una verificación de tipo estricta. Pero C++ es estrictamente verificación de tipos por lo que es necesario escribir cast malloc()
en C++.
fundición
void
punteros permite compilar el código como C++; algunas personas dicen que es una característica, yo diría que es un error;)– Cristóbal
14 de octubre de 2009 a las 17:29
también, lea los comentarios al primero de sus enlaces, ya que describe lo que debe hacer en lugar de enviar: codificación segura.cert.org/confluence/display/seccode/…
– Cristóbal
14 de octubre de 2009 a las 17:41
Seguiré el consejo de CERT para incluir al elenco. Además, nunca me olvidaré de incluir stdlib.h. 🙂
– Abhinav
20 de mayo de 2012 a las 18:29
Aquí hay un ejemplo SO de un error de tiempo de ejecución de compilación debido a la conversión
malloc
valor de retorno de: conversión aint*
en arco de 64 bits.– John_West
28 de diciembre de 2015 a las 18:02
esta pregunta está etiquetada
C
noC++
(son dos idiomas diferentes) Entonces, cualquier discusión (como en algunas de las respuestas) no es relevante para esta pregunta.– usuario3629249
9 de marzo de 2017 a las 18:15