12

This question asks what is the dynamic type of the object allocated by malloc and according to the top answer:

The return value of malloc is a block of uninitialized storage. No object has been constructed within that storage. And therefore it has no dynamic type.

This brings another question: at what point does it make sense to say that the storage returned by malloc gets a type. For example:

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

can we say that pi above points to an object of dynamic type int despite the fact that it is uninitialized?

Community
  • 1
  • 1
vitaut
  • 49,672
  • 25
  • 199
  • 336
  • I don't have the reference to hand, but as a holding non-answer, it's when you write an `int` to it. The reference is somewhere in the stuff about object lifetimes (specifically of POD types), if someone else wants to do the work and claim the glory. – Steve Jessop Mar 15 '16 at 23:45
  • @SteveJessop The stuff about object lifetimes does not say that (in C++14). – M.M Mar 15 '16 at 23:48
  • @M.M: oh, have they changed it then? – Steve Jessop Mar 15 '16 at 23:48
  • That section changes all the time – M.M Mar 15 '16 at 23:49
  • 2
    @SteveJessop There's an object there for C, IIRC, but not C++. – T.C. Mar 15 '16 at 23:52
  • The answer is still 'never '. Variables have types, at compile time, and a constructor can so operate on a block of memory as to equip it with RTTI information when accessed in the appropriate (standard-conforming) way, but even that isn't tantamount to saying that the memory acquires a type. What you can say about `p1` is that it is an `int` pointer into dynamic memory, but you can't say anything about 'an object of dynamic type `int`', because there isn't such a thing. – user207421 Mar 15 '16 at 23:54
  • @M.M. well, not *precisely* that, but as T.C. explains below it's when you write an `int` there *using a new-expression*. – Steve Jessop Mar 16 '16 at 00:20
  • @EJP: Formally, type indeed isn't a property of memory itself, type is a property of objects which can be located in memory. For conciseness, it makes sense to omit the object and transitively talk about the type of memory. – MSalters Mar 16 '16 at 11:04

2 Answers2

11

The status quo according to the standard is that there's no object there.

[intro.object]/1:

An object is created by a definition ([basic.def]), by a new-expression ([expr.new]) or by the implementation ([class.temporary]) when needed.

See also the discussion in P0137, which would make the above quote the definition of object:

Drafting note: this maintains the status quo that malloc alone is not sufficient to create an object.

(int *)p is none of these.

T.C.
  • 133,968
  • 17
  • 288
  • 421
  • So what if you do `*p = 0;`, is *that* then an object? Or are `int`s with static, automatic or thread storage duration objects because they're created by definitions, while `int`s with dynamic storage duration are not objects unless you use a new-expression, and none of the things the standard says about objects apply to them? – Steve Jessop Mar 16 '16 at 00:01
  • 3
    @SteveJessop `*p = 0` doesn't create an object, but `new (p) int()` creates one. – T.C. Mar 16 '16 at 00:02
  • So for example 1.9.12, "Accessing an object designated by a volatile glvalue (3.10), modifying an object, ... are all side effects". So is accessing `*(volatile int*)p` a side effect if and only if `*p` was initialized with new? – Steve Jessop Mar 16 '16 at 00:09
  • 2
    @SteveJessop If `p` has not been assigned to point to an object, accessing that glvalue induces undefined behavior. There's little point in arguing about its side effects if that is so. – Columbo Mar 16 '16 at 00:11
  • @Columbo: oh, I meant that volatile access to be after `*p = 0;`, which we've established doesn't create an object. – Steve Jessop Mar 16 '16 at 00:12
  • 2
    @SteveJessop That simply has undefined behavior, as `p` isn't pointing to an object. – Columbo Mar 16 '16 at 00:15
  • 3
    @SteveJessop That has always been technically UB, all the way back to C++03. – T.C. Mar 16 '16 at 00:17
  • @SteveJessop Unlike previous versions? In what version was that ever defined? The status quo was always that `malloc` merely provides storage, and that any access to raw storage is undefined. We're properly separating the valid from the invalid cases now; that doesn't mean that the invalid ones were valid beforehand. – Columbo Mar 16 '16 at 00:18
  • Ah well, luckily I just about never used `malloc` in C++ anyway. – Steve Jessop Mar 16 '16 at 00:28
  • 1
    @SteveJessop: Well, to be fair, while it is very much UB as defined by the standard, it will almost always *work* as well. Which is why most people don't bother with the placement new; they just do the pointer-cast and get on with their lives. – Nicol Bolas Mar 16 '16 at 01:14
  • 2
    If these comments are to believed, perfectly valid C programs suddenly became UB in C++ because the C++ Standard forgot to define how PODs can be created in uninitialized memory. I find it hard to believe such a basic concept has been overlooked for 18 years.. – MSalters Mar 16 '16 at 11:07
  • 1
    @MSalters: It's worth noting that many programs which were well-defined in C89 invoke Undefined Behavior under C99 for essentially the same reason, though it took a few years for compilers to get overly aggressive against them. In C++, if one calls the destructor on an object in allocated storage and uses placement new to construct an array of PODS in that same storage [avoiding the overhead and possibly fragmentation-inducing effects of freeing that storage] I believe items that are not written will at worst have Unspecified values. In C, array items which aren't written with anything... – supercat Mar 16 '16 at 22:28
  • 1
    ...of the proper type will be toxic, but there's no defined way to tell the compiler to treat a range of memory as an array of objects of a given type with Unspecified contents. – supercat Mar 16 '16 at 22:32
3

The answer is: when an object is created in the storage that malloc() allocates.

Note: malloc() is defined in the C standard and referenced in the C++ standard. Interactions with the C++ standard are intended for compatibility, not as a primary source.

What malloc() returns is a pointer to a unique region of storage (or NULL). It does not allocate or return an object. An object may be created in that storage by various means, and it is the object that has a type, not the storage.

The sample code given in the question creates a typed pointer, but has no effect on the storage.

david.pfx
  • 10,520
  • 3
  • 30
  • 63