在C ++ 20之前将malloc用于int未定义行为


95

有人告诉我,以下代码在C ++ 20之前具有未定义的行为:

int *p = (int*)malloc(sizeof(int));
*p = 10;

真的吗?

该论点是int对象的生存期在分配值之前没有开始(P0593R6)。若要解决此问题,new应使用放置:

int *p = (int*)malloc(sizeof(int));
new (p) int;
*p = 10;

我们真的必须调用一个琐碎的默认构造函数来启动对象的生存期吗?

同时,该代码在纯C语言中没有未定义的行为。但是,如果我int在C代码中分配一个并在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;

它仍然是未定义的行为吗?


8
int?否std::string?是。
Eljay

8
@Eljay For int,也是。只是如果您不这样做,它在实践中不会引起问题。对于std::string,这显然会引起问题。
巴里

在C ++ 20之前,您可以添加新的展示位置。这样就可以形成良好的格式,并且可能不会花费任何费用。
弗朗索瓦·安德列

8
C ++ 20中有哪些新规则可以改变这种情况?
凯文

4
不是int *p = (int*)malloc(sizeof(int)); p = new(p) int;吗?我曾经意识到,不分配位置new的结果也可能导致致命的后果(尽管看起来有些愚蠢)。
谢夫

Answers:


61

是真的吗

是。从技术上讲,它不属于:

int *p = (int*)malloc(sizeof(int));

实际上创建了一个类型的对象int,所以取消引用p是UB,因为那里没有实际的对象int

我们真的必须调用琐碎的默认构造函数来启动对象的生命周期吗?

是否必须按照C ++对象模型来避免C ++ 20之前的未定义行为?是。如果不这样做,编译器实际上会造成伤害吗?不是我知道的。

[...]它仍然是未定义的行为吗?

是。在C ++ 20之前的版本中,您实际上仍然没有int在任何地方创建对象,因此这是UB。


评论不作进一步讨论;此对话已转移至聊天
Makyen

为什么timsong-cpp.github.io/cppwp/n3337/basic.life#1.1中的语言不足以使其不能成为UB?毕竟,int在示例中获得了适当大小和对齐方式的存储-int对象的生命周期从此处开始。
avakar

41

是的,那是UB。int枚举了can可以存在的方法列表,但该方法不适用于此,除非您认为malloc是因果关系的。

人们普遍认为它是标准中的缺陷,但重要性不高,因为C ++编译器围绕UB的特定位进行的优化不会导致该用例出现问题。

至于第二个问题,C ++并不要求C ++和C如何交互。因此,所有与C的交互都是... UB,即C ++标准未定义的行为。


5
您能否在列举的方式上扩展一个int的存在方式?我记得我曾问过一个关于基本类型寿命的类似问题,并被告知基本类型可以“存在”,只是说它存在,因为规范没有另外说明。听起来我可能错过了该规范的有用部分!我想知道我应该阅读哪个部分!
科特·阿蒙

7
@CortAmmon [intro.object]中列举了对象(任何类型)在C ++ 20中存在的方式的清单:(1)根据定义(2)通过new-expression(3)根据新规则隐式地存在在P0593(4)中更改临时联合(5)的活动成员。(3)是C ++ 20中的新功能,(4)是C ++ 17中的新功能。
巴里

3
C / C ++交互真的是UB吗?由实现定义而不是未定义会更有意义,否则,甚至根本没有extern "C"语法也很奇怪。
罗斯兰

4
@Ruslan:实现可以自由定义ISO C ++未定义的任何行为。(例如gcc -fno-strict-aliasing,默认为MSVC)。说“定义的实现”将要求所有C ++实现定义它们与某些C实现互操作的某种方式,因此有意义的是完全由实现决定,无论他们是否愿意执行此类操作。
彼得·科德斯

4
@PeterCordes:我想知道为什么这么多人没有意识到IDB和UB之间的区别,而采用一种幻想的观点,即标准未能要求所有实现都有效地构造一个结构,这暗示着一个判断,即不应期望任何实现会这样做,不这样做的实现不得因此而被认为是劣等的。
超级猫
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.