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 intobjeto no se inicia antes de asignarle el valor ( P0593R6 ). Para solucionar el problema, se newdebe 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é intpasa 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 referenciaspes UB, ya que no hay ningún objeto realintallí.¿ 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
intobjeto en ningún lugar, así que esto es UB.fuente
inten el ejemplo se obtuvo un almacenamiento del tamaño y alineación adecuados : la vida útil delintobjeto comienza allí.Sí, fue UB. La lista de formas en que un
intenumeró 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.