Date: Sun, 28 Jul 2013 11:44:37 -0500
Ion Gaztañaga <igaztanaga_at_[hidden]> writes:
| El 26/07/2013 21:22, Gabriel Dos Reis wrote:
|
| > The oblique point I was making in the original reply was that C++'s
| > model requires that we work with objects, which means we work with
| > constructors and invariants guaranteed during construction or during the
| > object's lifetime. Maybe that was too oblique :-(
| >
| > We don't have a notion of an object's value before it existed.
| >
| >
| > I think so. It looks to me as if some of the "issues" raised in this
| > discussion implicitly make the assumption that there is a notion of an
| > object's value before its construction or lifetime, and such value is
| > preserved after construction. If that is the case, then I think those
| > issues are not properly formulated for C++'s fundamental object model.
|
| Then it appears that a lot of system programming done in C/C++ relies on
| UB and we can't find a correct way to achieve the same results with
| similart performance. AFAIK, all current compilers still do what
| programmers (wrongly) expect. So before optimizers start (correctly,
| according to the language specification) banning such uses, we need to
| formulate a simple way to allow low-level programming in C/C++, without
| limiting too many optimization opportunities.
|
| One straightforward way I can think of is to specify that the lifetime
| of an object (3.8 Object lifetime [basic.life]) of type T begins also when:
|
| -> the storage of unknown or [unsigned|signed] char static type with
| proper alignment is obtained (*) OR a value of integral type or
| enumeration type representing such storage is used.
|
| AND
|
| -> it's reinterpret_cast-ed to the type "pointer to T" (2)
|
| (1) A poor effort to limit aliasing to char arrays and mmap-like
| functions. With "unknown" data I would like to say void * storage
| returned by some system calls, but I don't know how to exclude the
| address of any storage converted to void*.
|
| (2) reinterpret_cast is chosen so that in C, a simple C-cast could
| achieve the same effect.
|
| Then in the reinterpret_cast section (5.2.10 Reinterpret cast
| [expr.reinterpret.cast]) a new pointer casting is allowed:
|
| "Converting a prvalue of type “pointer to T1” to the type “pointer to
| T2”, where “pointer to T1” is a pointer to an storage of unknown or
| [unsigned|signed] char type with proper alignment and size to hold T2,
| and T2 is an object type, the contents pointed by “pointer to T1” will
| become the object representation for an object of type T2. If contents
| of the storage are not a correct object representation for the object of
| type T2, the cast results in undefined behavior."
|
| Would somthing like this make any sense?
We shouldn't be doing anything in rash.
Also, I think we shouldn't be doing anything that attempts to circumvent
constructors. This issue has very subtle aspects.
Your proposed modification appears to go far beyond C. For example,
your point (2) would make just about any reinterpret_cast of *pointers*
change the lifetime of *objects*, even if the storage is actually never
accessed through that pointer.
Again, I would plead that we approach the issue and possible
resolutions, not as an arms race against optimizers. Today we are
worrying about program transformations that can dispense with certain
operations ("optimizations"), tomorrow we will worry about safety;
after tomorrow, security; etc.
-- Gaby
| El 26/07/2013 21:22, Gabriel Dos Reis wrote:
|
| > The oblique point I was making in the original reply was that C++'s
| > model requires that we work with objects, which means we work with
| > constructors and invariants guaranteed during construction or during the
| > object's lifetime. Maybe that was too oblique :-(
| >
| > We don't have a notion of an object's value before it existed.
| >
| >
| > I think so. It looks to me as if some of the "issues" raised in this
| > discussion implicitly make the assumption that there is a notion of an
| > object's value before its construction or lifetime, and such value is
| > preserved after construction. If that is the case, then I think those
| > issues are not properly formulated for C++'s fundamental object model.
|
| Then it appears that a lot of system programming done in C/C++ relies on
| UB and we can't find a correct way to achieve the same results with
| similart performance. AFAIK, all current compilers still do what
| programmers (wrongly) expect. So before optimizers start (correctly,
| according to the language specification) banning such uses, we need to
| formulate a simple way to allow low-level programming in C/C++, without
| limiting too many optimization opportunities.
|
| One straightforward way I can think of is to specify that the lifetime
| of an object (3.8 Object lifetime [basic.life]) of type T begins also when:
|
| -> the storage of unknown or [unsigned|signed] char static type with
| proper alignment is obtained (*) OR a value of integral type or
| enumeration type representing such storage is used.
|
| AND
|
| -> it's reinterpret_cast-ed to the type "pointer to T" (2)
|
| (1) A poor effort to limit aliasing to char arrays and mmap-like
| functions. With "unknown" data I would like to say void * storage
| returned by some system calls, but I don't know how to exclude the
| address of any storage converted to void*.
|
| (2) reinterpret_cast is chosen so that in C, a simple C-cast could
| achieve the same effect.
|
| Then in the reinterpret_cast section (5.2.10 Reinterpret cast
| [expr.reinterpret.cast]) a new pointer casting is allowed:
|
| "Converting a prvalue of type “pointer to T1” to the type “pointer to
| T2”, where “pointer to T1” is a pointer to an storage of unknown or
| [unsigned|signed] char type with proper alignment and size to hold T2,
| and T2 is an object type, the contents pointed by “pointer to T1” will
| become the object representation for an object of type T2. If contents
| of the storage are not a correct object representation for the object of
| type T2, the cast results in undefined behavior."
|
| Would somthing like this make any sense?
We shouldn't be doing anything in rash.
Also, I think we shouldn't be doing anything that attempts to circumvent
constructors. This issue has very subtle aspects.
Your proposed modification appears to go far beyond C. For example,
your point (2) would make just about any reinterpret_cast of *pointers*
change the lifetime of *objects*, even if the storage is actually never
accessed through that pointer.
Again, I would plead that we approach the issue and possible
resolutions, not as an arms race against optimizers. Today we are
worrying about program transformations that can dispense with certain
operations ("optimizations"), tomorrow we will worry about safety;
after tomorrow, security; etc.
-- Gaby
Received on 2013-07-28 18:44:59