Dangling pointers in containers (undefined behavior)

Started by
17 comments, last by mfawcett 17 years ago
Quote:Original post by mfawcett
I agree with you MaulingMonkey, which is why I tried to caveat every post with "in practice it's not an issue", or "in my own code I don't even worry about this" type phrases. Your tone is less than pleasant, however.


If you've expected pleasantries from me, it's clear you've confused me with some other monkey. Monkey Jesus, prehaps. Or Monkey Budah.


There's a reason my nick isn't MassagingMonkey.


That said, given that I've linked one of my favorite webcomics for relevant humor, sharing this possibly previously unknown (to you) gem of humor (as it is in my opinion), I'm left wondering why my above-par jollyness is interpreted as sub-par compared to the expected.


I replied to this post as a result of being named in the original post. I felt a post detailing why I would not continue the discussion to be relevant, and so it was supplied. Do with it what you will. I've already stated what I'll do.
Advertisement
I'm not sure whether the Standard can specify any stronger guarantees regarding singular/dangling pointers without needlessly limiting the range of potential hardware on which a C++ program can be run.

For instance, I can certainly imagine a security-enhanced CPU where the mere act of loading an invalid(* pointer to a register triggers a hardware trap or an interrupt, specifically to catch unitialized pointers before doing something much worse, such as using them as jump addresses.

*) an invalid bit pattern, or a value outside of the memory allocated for the process.
Quote:Original post by Sharlin
I'm not sure whether the Standard can specify any stronger guarantees regarding singular/dangling pointers without needlessly limiting the range of potential hardware on which a C++ program can be run.

For instance, I can certainly imagine a security-enhanced CPU where the mere act of loading an invalid(* pointer to a register triggers a hardware trap or an interrupt, specifically to catch unitialized pointers before doing something much worse, such as using them as jump addresses.

*) an invalid bit pattern, or a value outside of the memory allocated for the process.


As far as I see, such register would have to be dedicated to memory addresses only and thus needed to be used only when accessing memory indirectly through it. A compiler backend could store the pointer in a general purpose register until the pointer would actually be dereferenced.
Look up the section on reinterprete_cast<>() in the standard im pretty sure it uses the same wording, however i dont have a copy to check, and its a similar context hence since im pretty sure its valid to copy the result of reinterprete_cast id say copying a dangling pointer is valid.

Of course if im wrong about what the standard says on reinterprete_cast<>() then just ignore me :)
Quote:Original post by Julian90
Look up the section on reinterprete_cast<>() in the standard im pretty sure it uses the same wording, however i dont have a copy to check, and its a similar context hence since im pretty sure its valid to copy the result of reinterprete_cast id say copying a dangling pointer is valid.

Of course if im wrong about what the standard says on reinterprete_cast<>() then just ignore me :)


I looked up the section. From what I can tell, the result of reinterpret_cast can either be specified, unspecified, implementation defined, or result in UB. It says nothing about what happens when you copy those values, just that the cast will result in one of the 4 behaviors.
--Michael Fawcett
Quote:Original post by MaulingMonkey
That said, given that I've linked one of my favorite webcomics for relevant humor, sharing this possibly previously unknown (to you) gem of humor (as it is in my opinion), I'm left wondering why my above-par jollyness is interpreted as sub-par compared to the expected.


I replied to this post as a result of being named in the original post. I felt a post detailing why I would not continue the discussion to be relevant, and so it was supplied. Do with it what you will. I've already stated what I'll do.


Apologies, I must have read into something from your post that wasn't there. That's the Internet for you...
--Michael Fawcett
Quote:Original post by Enigma
So your argument against dangling pointers in SC++L containers is (correct me if I'm wrong) that the containers are allowed to copy contained values at any time and that copying an invalid pointer value is undefined behaviour:
int * i = new int;delete i;int * j = i; // undefined behaviour.



Yes, apparently even the C standard says so.
This thread details it.

*Any* use other than assignment is UB. That means that an invalid pointer is not copyable.

Apparently there have also been architectures that existed(still exist?) where copying an invalid pointer did lead to a hardware trap. (I did not know about this until recently).

Quote:Original post by Enigma
I'm quite prepared to be proven wrong, but I'm afraid I'm going to require you to be far more persuasive than you have been so far.


STD Containers require their elements be Copyable and Assignable. They do not specify time constraints as to when that might be, so that means the elements must be Copyable and Assignable always (when in the container). The moment you delete a pointer that still exists in a container, you have UB, regardless if immediately after you do a clear().

The temporary in my code was for that specific reason.
T *ptr = vec.back();vec.pop_back();delete ptr;


It *did* serve a purpose.
--Michael Fawcett
I agree with you that SC++L containers require CopyConstructible and Assignable elements. I disagree that the C++ Standard states that a deleted pointer value is not CopyConstructible or Assignable. The thread you linked to quotes from the C99 standard. In C99 it seems quite clear that copying a deleted pointer value is undefined behaviour. In C89 it could be argued that copying a deleted pointer value is undefined behaviour (based on the draft copy I read). The C++ Standard, which was based on the C89 standard contains nothing that I can find to suggest that copying a deleted pointer value is undefined behaviour. This may be a defect in the C++ Standard, but I have yet to see a convincing argument for copying a pointer with indeterminate value to be undefined behaviour in C++.

In fact just looking again the C++ standard even contains an example when an object (not a pointer) with indeterminate value is copied, and no reference is made to this being undefined behaviour:
Quote:C++ Standard, Section 3.3.1, Paragraph 1
The point of declaration for a name is immediately after its complete declarator (clause 8) and before its initializer (if any), except as noted below. [Example:

int x = 12;
{ int x = x; }

Here the second x is initialized with its own (indeterminate) value. ]

Σnigma
4.1p1 (Lvalue to rvalue conversions): "If the object to which the lvalue refers ... is uninitialized, a program that necessitates this conversion has undefined behavior."

That's only in reference to your latest post. I don't think it has bearing on invalid pointers, but I could be mistaken.
--Michael Fawcett

This topic is closed to new replies.

Advertisement