Pregunta sobre el uso de la implementación realloc en código C ++
-
06-07-2019 - |
Pregunta
Amigos
En nuestro C ++, Iam actual usando el método realloc para redimensionar la memoria asignada por malloc. el uso de realloc () se realiza de la siguiente manera
my_Struct *strPtr =(my_struct*)malloc(sizeof(my_Struct));
/* an later */
strPtr = (my_struct*)realloc(strPtr,sizeof(my_Struct)*NBR);
ahora wikipeadia (_http: //en.wikipedia.org/wiki/Malloc) dice que
Si en cambio uno lo hizo
void *p = malloc(orig_size);
/* and later... */
p = realloc(p, big_size);
entonces, en caso de que no sea posible obtener bytes de memoria de gran tamaño, p tendrá un valor NULL y ya no tendremos un puntero a la memoria previamente asignada para p, creando una pérdida de memoria
Y también dice que la forma correcta de rectificar el error anterior es
void *p = malloc(orig_size);
/* and later... */
void *tmp = realloc(p, big_size);
if (tmp != NULL)
{
p = tmp; /* OK, assign new, larger storage to p */
}
else
{
/* handle the problem somehow */
}
¿Puede decirme cuál es la mejor manera de usar realloc ()
también una vez que tengo un puntero a una estructura y luego, mientras uso realloc, ¿puedo usar el puntero a un vacío ???
Muchas gracias
Solución
Por supuesto, debe protegerse contra el caso que realloc()
devuelve NULL
. Es una asignación de memoria, y en C (donde <=>) se usa principalmente, creo que los programadores de C ++ piensan que es un poco bajo nivel / qaint usar llamadas en bruto <=>, las asignaciones de memoria siempre pueden fallar.
Sobrescribir directamente el puntero con el valor de retorno es un error, ya que deja caer el puntero original y hace que la memoria pierda en caso de que falle la reasignación.
Otros consejos
Malloc () y realloc () son funciones de C. En realidad, realloc () hace malloc () y free () dependiendo de los argumentos que pase:
- Si le pasa un puntero nulo, realloc hace lo que hace malloc.
- Si pasa un tamaño cero, realloc hace lo que hace gratis.
Citado de Aquí , donde tiene una explicación más profunda.
La biblioteca de C hace que sea imposible expandir un bloque de memoria en su lugar, por lo que C ++ tampoco lo admite.
Si desea apegarse a las funciones de C, debe mantener el puntero de su primera asignación de memoria al llamar a realloc (). Luego verifica si es NULL, de lo contrario lo asigna, tal como lo hizo en su último código.
Pero quizás para C ++ la mejor solución es hacer su propio mallocator, la solución estándar basada en malloc de C (). Marque esto , o esto .
Utilice el enfoque sugerido & # 8211; mantenga el puntero al búfer anterior hasta que realloc haya regresado con éxito. Una vez que realloc () devuelve con éxito, el bloque anterior se ha liberado y todos los punteros a él se han colgado & # 8211; ajustarlos.
a realloc y malloc no les importa cuál es el tipo de puntero: puede usar void * así como cualquier cosa *.
Como han dicho otros, simplemente use realloc correctamente como se sugiere.
Pero la " forma C ++ " de hacer esto es realmente usar un std :: vector < > en lugar de mantener matrices usted mismo. De esa manera, la biblioteca estándar de C ++ se encargará de los detalles de bajo nivel de reasignación (presumiblemente mediante el uso de realloc ()).
Cuando realloc () falla y devuelve NULL, la memoria original queda intacta.
Entonces deberías usarlo así:
my_Struct* strPtr =(my_struct*)malloc(sizeof(my_Struct));
/* an later */
my_Struct* tmp = (my_struct*)realloc(strPtr,sizeof(my_Struct)*NBR);
if (tmp != NULL)
{
strPtr = tmp;
}
else
{
/* realloc Failed. Need to do something */
}
¿Por qué estás usando malloc y realloc? Casi siempre hay una mejor manera en C ++.
Si lo está utilizando para hacer matrices de longitud variable, es casi seguro que esté mejor con std :: vector < > ;, o tal vez una de las otras plantillas de contenedor.
Si en su lugar usa C, quizás con un compilador compatible con C ++, entonces la forma correcta es el segundo método, que no pierde un bloque de memoria completo cuando no se puede asignar.
La respuesta a su segunda pregunta también depende de si está utilizando C o C ++. En C, void * es un tipo de puntero de datos genérico y es libremente convertible. En C ++, void * debe convertirse explícitamente. Si realmente está escribiendo C, debe usar malloc () y amigos, que funcionan en void *. Si realmente está escribiendo C ++, necesita emitir, lo que lo hace más incómodo. En ninguno de los casos, realloc () funciona en punteros para estructurar, sino en punteros para anular.