From: David Abrahams on
"Andrei Alexandrescu (See Website For Email)"
<SeeWebsiteForEmail(a)erdani.org> writes:

> David Abrahams wrote:
>> "Andrei Alexandrescu (See Website For Email)"
>>>But in a memory-safe program you don't even need Purify to tell you that
>>>the program did something wrong. A logging module would suffice, and the
>>>proof is in the trace.
>>
>>
>> a. I don't see how the logging module can do that
>> b. Anyway, that's often far too late to actually debug the problem.
>
> Am I not getting a joke? Logs are the _best_ way to debug a program.

Are you really telling me that regardless of the type of program, the
best way to debug is always by using a log? What if the log didn't
capture the information you needed?

>> Of course not. That's a cute comeback but misses the point entirely.
>> In a GC'd system Purify is the wrong tool because there are no invalid
>> pointers. Instead you need a tool that tells you that something has
>> been kept alive too long, and nobody's figured out a tool to do that
>> because it's effectively impossible for a tool to tell what "too long"
>> is.
>
> Ehm. I thought we were talking about arbitrary memory overwrites. Maybe
> I did miss the point entirely.

I guess so. We were talking more generally about using a pointer to
an object that another part of your program thought it had torn down
or caused to disappear. In C++ that translates into arbitrary memory
overwrites which can sometimes be detected by the OS or an external
tool; in Java that translates into the use of a zombie object, which
can never be detected except maybe by the addition of handwritten
asserts to your code.

>>>The memory-safe program wins because it never overwrites arbitrary
>>>memory; so all objects unaffected by a bug respect their invariants.
>>
>> The same is trivially true of C++: all objects unaffected by a bug
>> respect their invariants.
>
> This is wrong.

How can it possibly be wrong?

> A memory bug in C++ can affect any object.

Sure.

> You could say, yeah, all objects unaffected by a bug have no
> problem.

Yeah, I do say that.

> The problem is, you can't define the set of objects unaffected by a
> bug :o). Right back atcha.

That doesn't make my statement wrong. Your original claim was
tautological. If you want to make this other claim, great, let's work
with that one.

I understand that if you believe certain "sealed" subsystems (like a
logging module) are themselves bug-free then you don't need to look at
them for the cause of your bug... but then you wouldn't look to such a
system in a C++ program either, even if it *can* get stomped by
erroneous code.

I guess I just don't see any black-and-white difference here. Can you
help me understand how this advantage plays out in practice?

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Binglong X on

Mirek Fidler wrote:
>
> BTW, the really cool implementation would store complex in single SSE2
> register and use single ADDPD opcode to perform addition.
>
> Interestingly, using intrinsics already present in GCC, it could be
> done even now as library solution. Which is in the end more fruitful
> approach than to introduce complex as fundamental type.
>

But a compiler would be free to use SSE2 registers as well to store a
complex if complex is introduced as a fundamental type into a language?
Using a nonportable library to supplement the current language is a
good plus, why is it more fruitful than supporting that in the core of
another language?


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: David Abrahams on
"Andrei Alexandrescu (See Website For Email)"
<SeeWebsiteForEmail(a)erdani.org> writes:

> David Abrahams wrote:
>> "Andrei Alexandrescu (See Website For Email)"
>>>>That said, even in a system with no undefined behavior, we have no
>>>>idea what the value of x (or anything else in our program) is after a
>>>>programming error, so the ability to continue on with the program
>>>>executing the instructions you thought you were giving it originally
>>>>is not as valuable as it might at first seem.
>>>
>>>It's not "anything else in our program". It's "anything else in our
>>>program that was affected by x"
>>
>>
>> No, not at all. Re-read the scenario; "x" didn't necessarily have
>> anything to do with the programming error. From a practical point of
>> view, by the time your internal checks/assertions have detected that
>> there's been a programming error by inspecting some piece of program
>> state (call it Z), you have no idea how far the damage has spread.
>> That is, the program's own guarantees are out the window.
>
> I disagree. As I explained before: in Java bugs can be made modular in
> ways that are not possible in C++, because you have true memory
> isolation between objects.

True memory isolation is very nice, but I don't see how it helps make
bugs modular in practice. Once you discover something is wrong you
have no way of knowing where the code causing the wrongness was or
what the wrongness has affected [see below].

When I make that claim about C++ I am never thinking specifically
about references through invalid pointers, because that basically
never happens to me anymore. I'm just thinking about what happens to
the program state.

One way to think of this is that if you imagine the use of
FORTRAN-style data structures with indexing instead of pointers (and
actually I think in some sense you need these in Java because there's
no pointer arithmetic), even integers can "dangle." Just shorten an
array and there you are. So I don't think there's anything intrinsic
in keeping pointers valid (even if valid only means pointing to an
object that should really be gone) that limits the spread of broken
invariants.

[below] Okay, I suppose it's possible to write subsystems that make
absolutely no assumptions about what their clients pass other than
what's guaranteed by the type system, and if those subsystems have no
bugs, you know these subsystems still intact -- a valuable property
for diagnostic subsystems like loggers.

However, I doubt the practicality of writing whole systems that way.
Eventually you'll end up with functions that require a certain
relationship between parameters (e.g. end >= begin), and then to
maintain the "no assumptions about the inputs" stance you have to
check these relationships, and throwing an exception becomes part of
the function's defined behavior. Since the function calling with
arguments (end < begin) is already holding broken data or broken
assumptions, all hell then breaks loose.

>> Meaning that in Java, all writes of "references" (a.k.a. pointers) are
>> synchronized?
>
> That is correct. They are guaranteed to be atomic; there is no invalid
> reference in Java, ever, period.

Wow; that does sound slow :)

>>>and because there's no pointer forging, that reduces to "any other
>>>number that was affected by x", which considerably reduces the rot
>>>in the program and the difficulty in spotting it. I guess all I can
>>>say is that I tend to see that guarantee as much more valuable. :o)
>>
>> Than what?
>
> Than "all the hell breaks loose starting at this point".

Oh, but that's not guaranteed either. If you're going to compare
value, you should compare the Java guarantee against:

* better speed
* the flexibility to respond to errors in special ways
* (I had another but then it flitted away)

Anyway, I'm not claiming to know what's more valuable in the long run,
I'm just challenging what I think are some of the usual assumptions
around this question, one of goes something like, "undefined behavior
in a language has no merits."

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Walter Bright on
Jeffrey Yasskin wrote:
> On Dec 4, 7:30 am, Walter Bright <wal...(a)digitalmars-nospamm.com>
> wrote:
>> In C++, core arrays have one subset of needed array features, and
>> std::vector has the other subset of needed array features. The problemhttp://groups-beta.google.com/group/comp.lang.c++.moderated/browse_thread/thread/a048420165ad4719/7fa216cbf715a79e
>> is the two don't combine with each other to create full featured arrays.
>>
>> BTW, the array example in D would be:
>>
>> int[] a = [1, 2, 3, 42, 66];
>> writefln(a.length);
>
> The array example in C++0x will be:
> vector<int> a = {1, 2, 3, 42, 66};
> std::cout << a.size();
> See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2100.pdf
> (initializer lists).

It's a nice (but complicated) proposal, and does plug a major gap. It
has never been implemented (at least the proposal doesn't mention any
implementation experience). Like a paper airplane (aerospace jargon for
an airframe that exists only as blueprints), we don't know if it'll fly
or not until the durn thing leaves the tarmac.

> Yes, it took longer to come up with a language
> extension that enabled a library solution. But doing so meant that
> _any_ library type could take advantage of it, rather than needing a
> patch to the compiler for every type you want a good syntax for.

It'll be many years before this is implemented in enough compilers to
make it usable. And it's still just not as nice a syntax as core arrays,
and it still does not interoperate with core arrays. (D's arrays
interoperate with C arrays.) For a ubiquitous type like arrays, the
sugar is worth it.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Mirek Fidler on

Binglong X wrote:
> But a compiler would be free to use SSE2 registers as well to store a
> complex if complex is introduced as a fundamental type into a language?
> Using a nonportable library to supplement the current language is a
> good plus, why is it more fruitful than supporting that in the core of
> another language?

Right, BUT this way I can use SSE2 to build optimized library for
anything else beyond complex datatype.

It is quite easy to maintain (e.g. using #ifdefs) optimized parts that
compile on relevant platforms.

Mirek


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]