Me dijeron que el siguiente código tiene un comportamiento indefinido hasta C ++ 20:
int *p = (int*)malloc(sizeof(int));
*p = 10;
¿Es eso cierto?
El argumento fue que la vida útil del int
objeto no se inicia antes de asignarle el valor ( P0593R6 ). Para solucionar el problema, se new
debe utilizar la ubicación :
int *p = (int*)malloc(sizeof(int));
new (p) int;
*p = 10;
¿Realmente tenemos que llamar a un constructor predeterminado que sea trivial para iniciar la vida útil del objeto?
Al mismo tiempo, el código no tiene un comportamiento indefinido en C. puro. Pero, ¿qué int
pasa si asigno un código en C y lo uso en código C ++?
// C source code:
int *alloc_int(void)
{
int *p = (int*)malloc(sizeof(int));
*p = 10;
return p;
}
// C++ source code:
extern "C" int *alloc_int(void);
auto p = alloc_int();
*p = 20;
¿Sigue siendo un comportamiento indefinido?
c++
malloc
undefined-behavior
c++20
anton_rh
fuente
fuente
int
? No.std::string
¿ Para ? Si.int
, también sí. Es solo que no causará problemas en la práctica si no lo hace. Porquestd::string
, obviamente, causará problemas.int *p = (int*)malloc(sizeof(int)); p = new(p) int;
? Una vez me di cuenta de que no asignar un resultado nuevo a la ubicación también puede causar efectos fatales (aunque puede parecer un poco tonto).Respuestas:
Si. Técnicamente hablando, no forma parte de:
int *p = (int*)malloc(sizeof(int));
en realidad crea un objeto de tipo
int
, por lo que la eliminación de referenciasp
es UB, ya que no hay ningún objeto realint
allí.¿ Tiene que seguir el modelo de objetos de C ++ para evitar un comportamiento indefinido antes de C ++ 20? Si. ¿Algún compilador realmente causará daño si no haces esto? No que yo supiese.
Si. Antes de C ++ 20, todavía no creaste un
int
objeto en ningún lugar, así que esto es UB.fuente
int
en el ejemplo se obtuvo un almacenamiento del tamaño y alineación adecuados : la vida útil delint
objeto comienza allí.Sí, fue UB. La lista de formas en que un
int
enumeró la puede existir, y ninguna se aplica allí, a menos que usted sostenga que malloc es causal.Se consideró ampliamente una falla en el estándar, pero de poca importancia, porque las optimizaciones realizadas por los compiladores de C ++ alrededor de ese bit particular de UB no causaron problemas con ese caso de uso.
En cuanto a la segunda pregunta, C ++ no exige cómo interactúan C ++ y C. Entonces, toda interacción con C es ... UB, también conocido como comportamiento no definido por el estándar C ++.
fuente
extern "C"
sintaxis.gcc -fno-strict-aliasing
, o MSVC por defecto). Decir "implementación definida" requeriría que todas las implementaciones de C ++ definan alguna forma en la que interoperan con alguna implementación de C, por lo que tiene sentido dejar completamente a la implementación si quieren hacer algo así o no.