Teaching new tricks to an old dog (C++ -->Ada)

  • Thread starter Turamnvia Suouriviaskimatta
  • Start date
P

Peter Koch Larsen

Tapio Kelloniemi said:
Yes, but I can tell the compiler that I know better:
V : Velocity := Velocity (Integer (M) / Integer (S));

You can't be serious here. You just did what corresponds to a C-style cast
here. Would anyone accept that in production-code? The other proposal (to
create a function) simply requires a vast amount of stupid code if all
"normal" generic dimensions.
Also other readers of my code now know surely that this is what I meant.

So they say, the ones who abuses C-style casts.
Not so. There is an excellent library which does exactly what you want -
using templates, of course.

That is a good thing. If all C++ programmers used it, I think their
programs would benefit a lot of it.
What makes you believe they happen regularly in C++?

They just happen. Why people had otherwise created such tools as valgrind
(http://valgrind.kde.org/). I also use it myself for Ada to eliminate
memory
leaks. Writing past array bounds unintentionally is quite easy. In Ada
Constraint_Error is raised, but C++ program segfaults. Or even worse, it
does not segfault immediately, but when the function is exited (as the
return address has been destroyed). STL is safer, but it cannot always be
used (eg. when interfacing to foreign code).
An example. First compile with the default behaviour, then with all
warnings tu
rned on: [--]
If a replace I < J; with null; the result is:
gcc -c -gnatg temp.adb
temp.adb:2:04: warning: "I" is not modified, could be declared constant
temp.adb:2:04: warning: variable "I" is not referenced
temp.adb:3:04: warning: "J" is not modified, could be declared constant
temp.adb:3:04: warning: variable "J" is not referenced
gnatmake: "temp.adb" compilation error

I see no real difference here between a good-quality C++ compiler and Ada.

Another example:

int* f()
{
int i = 3;
int& l = *(new int);

l = i;
int* p = &i; // Should be int* p = &l;

return p;
}

int main()
{
int* p = f();
*p = 4;
return 0;
}

# g++ -Wall -o temp temp.cc
#

Not even a warning and the program does not crash on my system! Valgrind
revealed the error (and thought it was a G++ bug).
If the code above is modified a bit, even the best compiler cannot
know for sure that we are doing evil things.

Noone denies that writing code such as this is possible in C++. Apparantly
you can also do it in Ada. In neither language will you see such stuff in
production-code. This at least is my sincere hope ;-)
The same in Ada:

procedure Temp is
type Int_Ptr is access Integer;

function F return Int_Ptr is
I : Integer := 3;
L : Int_Ptr := new Integer;
P : Int_Ptr;
begin
L.all := I;
P := I'Access; -- Should be P := L;
return P;
end F;

A : Int_Ptr;
begin
A := F;
A.all := 4;
end Temp;

# gcc -c -gnatg temp.adb
temp.adb:5:04: (style): subprogram body has no previous spec
temp.adb:11:12: prefix of "Access" attribute must be aliased

So if I really want to pass a pointer to a local to the caller, I should
change
I : Integer := 3;
to
I : aliased Integer := 3;

Also note that the lines which were "mistyped" are much closer to each
other in C++ than in Ada.

/Peter
 
M

Martin Krischik

Certainly far from impossible though, This is what I get from lint for
that

|
{
e:\cygwin\home\radsett\newlib-lpc\fram.c 98 Note 957: Function 'fun'
defined
without a prototype in scope

|
p = &a;
e:\cygwin\home\radsett\newlib-lpc\fram.c 100 Info 789: Assigning
address of
auto variable 'a' to static

Yes if only it where build into the compiler. And yes I do use lint - but
lint build into the compiler would be more helpfull.

BTW: this example is not far fetched because I actually hat problem. And not
as a beginner - this can problem invisibly happen in combination with an
implicit type convertsion.

The type conversion creates a - hidden - temporary whose address is then
passed into on.

Which brings be to a little C++ language lawyer question. Who was right IBM
or MS:

(For my defence in making that silly mistake: the code was scattered over
several files.)

//
// consider that key() returns a reference with sufficient livespan.
//
class Data
{
unsigned&
key ();
}

//
// For a template a free key () function was needed which returns a
// reference to the key data.
//
int&
key (Data const& Element)
{
return Element.key();
}

IBM C++ converts unsigned& -> int&
MS C++ converts unsigned& -> unsigned -> int -> int&

So which compiler was right, which wrong?

(Please don't tell my how to fix it: Once found I knew what to do.)

Martin
 
M

Martin Krischik

You can't be serious here. You just did what corresponds to a C-style cast
here.

Not, actually it is checked convertion:

http://en.wikibooks.org/wiki/Programming:Ada:Subtypes#Checked_Conversion
Would anyone accept that in production-code?

I think so. After all it is not an unchecked convertion:

http://en.wikibooks.org/wiki/Programming:Ada:Subtypes#Unchecked_Conversion
The other proposal (to
create a function) simply requires a vast amount of stupid code if all
"normal" generic dimensions.

Yes that is indeed a sore point - and no solution in sight.

Martin
 
M

Martin Dowie

Martin said:
Yes that is indeed a sore point - and no solution in sight.

There is one solution from Christoph Grein, see

http://home.t-online.de/home/Christ-Usch.Grein/Ada/SI.html

But a solution 'built-in' to the language didn't make it into Ada0Y. The
reference implementation for it is available but it doesn't solve 100%
of cases, so was dropped.

I believe Tucker had an idea for another proposal involving pragmas
but time ran out, so I don't think that even made it into an AI.

Cheers

-- Martin
 
I

Ioannis Vranos

Martin said:
Yes if only it where build into the compiler. And yes I do use lint - but
lint build into the compiler would be more helpfull.

BTW: this example is not far fetched because I actually hat problem. And not
as a beginner - this can problem invisibly happen in combination with an
implicit type convertsion.

The type conversion creates a - hidden - temporary whose address is then
passed into on.

Which brings be to a little C++ language lawyer question. Who was right IBM
or MS:

(For my defence in making that silly mistake: the code was scattered over
several files.)

//
// consider that key() returns a reference with sufficient livespan.
//
class Data
{
unsigned&
key ();
}


You shouldn't return a non-const reference to the data of a Class.


//
// For a template a free key () function was needed which returns a
// reference to the key data.
//
int&
key (Data const& Element)
{
return Element.key();
}

IBM C++ converts unsigned& -> int&


This doesn't make any sense. You mean it did something like:


unsigned u;

int &r= u;
 
M

Martin Krischik

You shouldn't return a non-const reference to the data of a Class.

Don't tell me - I allready know. Tell the IBM Team which developed the Open
Class Library. While I like the OCL more then the STL the implementation
for key access for the IKeySortedSet had potential for improvement.
This doesn't make any sense. You mean it did something like:

Did you read the posting? I never said it made sense - I said it was a
programming mistake I made a few yeast ago which is still nagging me.

M:\AAA\BBB\CCC\XXX.hpp:
unsigned u;
N:\DDD\EEE\FFF\YYY.cpp:

int &r= u;

Am I the only C++ programmer in the world who understands that those little
programming mistakes never ever happen in two lines of code - one needly
above the other.

No they happen because one line is in one file and the other in another
file. Both files of course in different directories. And on OS/2 / Windows
both Directories on different drives. And - last not least - both written
by different programmers.

But that is all off topic - as I wanted a clarification from a language
lawyer if a temporary should be used in an implicit convertion of unsigned&
to int&.

Martin
 
I

Ioannis Vranos

Martin said:
Did you read the posting? I never said it made sense - I said it was a
programming mistake I made a few yeast ago which is still nagging me.


I was talking about whether the compiler did something like (notice the "it did" part):



The compiler did something like that? Well if yes, I suppose the compiler uses the same
implementation of signed and unsigned references, so it did it directly.
 
?

=?ISO-8859-1?Q?Falk_Tannh=E4user?=

Martin said:
But that is all off topic - as I wanted a clarification from a language
lawyer if a temporary should be used in an implicit convertion of unsigned&
to int&.

IANALL, but binding an lvalue of type unsigned to a reference to int
(or more generally an lvalue of one type to a reference to a different
type when there is no inheritance relationship between these types)
is not allowed and will be rejected by any conforming compiler.
What is possible is:
- Binding an lvalue to a reference of another (incompatible) type
using a cast:
unsigned u = 42;
int& ri = reinterpret_cast<int&>(u);
In this case, no temporary is involved, 'ri' is just an alias for 'u'
but with a different type.
or
- Binding a value (not necessarily an lvalue) to a const-qualified
reference:
unsigned u = 42;
int const& ri1 = u;
int const& ri2 = 666;
Here, temporaries are created that will live as long as does the
reference they are bound to.

Falk
 
M

Martin Krischik

Falk said:
IANALL, but binding an lvalue of type unsigned to a reference to int
(or more generally an lvalue of one type to a reference to a different
type when there is no inheritance relationship between these types)
is not allowed and will be rejected by any conforming compiler.

Thank you, that is indeed good news since there is hope that silly bugs like
that won't happen in future.

Martin
 
M

Martin Krischik

Ioannis said:
I was talking about whether the compiler did something like (notice the
"it did" part):

Ahh, sorry. Well - they did - both IBM C++ V 3.08 and MS-C V. 7.00.
The compiler did something like that? Well if yes, I suppose the compiler
uses the same implementation of signed and unsigned references, so it did
it directly.

Only they both did it differently - one (IBM) directly and the other (MS)
using a temporary.

Now do guess my supprise. The code did work for 3 or 4 years and then was
ported to MS-C++ and kaboom.

And since it was legacy code it took ages to debug. Normally you look at the
most recent changes. But having made no changes at all - only porting from
one compiler to the next - there where no starting point all all - just a
program which crashes deep inside the container library.

Martin
 
I

Ioannis Vranos

Martin said:
Only they both did it differently - one (IBM) directly and the other (MS)
using a temporary.

Now do guess my supprise. The code did work for 3 or 4 years and then was
ported to MS-C++ and kaboom.

And since it was legacy code it took ages to debug. Normally you look at the
most recent changes. But having made no changes at all - only porting from
one compiler to the next - there where no starting point all all - just a
program which crashes deep inside the container library.


Well, you can't depend on having an unsigned int pointed by a signed reference. However I
wonder how it did compile. For example the code:


class SomeClass
{
unsigned x;

public:

unsigned &getx() { return x; }
};


int &crazyfunc(SomeClass &obj)
{
return obj.getx();
}



int main()
{
SomeClass obj;

int &r= crazyfunc(obj);
}


produces the following errors, when used directly without any compiler switch:


GCC 3.4.2:

temp.cpp: In function `int& crazyfunc(SomeClass&)':
temp.cpp:13: error: invalid initialization of reference of type 'int&' from expr
ession of type 'unsigned int'


VC++ 2003:

temp.cpp
temp.cpp(13) : error C2440: 'return' : cannot convert from 'unsigned int' to 'in
t &'
A reference that is not to 'const' cannot be bound to a non-lvalue


Intel C++ 8.1:

temp.cpp
temp.cpp(13): error: a reference of type "int &" (not const-qualified) cannot be
initialized with a value of type "unsigned int"
return obj.getx();
^

compilation aborted for temp.cpp (code 2)
 
M

Martin Krischik

Ioannis said:
Well, you can't depend on having an unsigned int pointed by a signed
reference. However I wonder how it did compile. For example the code:

Falk Tannhäuser allready pointed out that is is illegal and am glad for
that.
VC++ 2003:

temp.cpp
temp.cpp(13) : error C2440: 'return' : cannot convert from 'unsigned int'
to 'in t &'
A reference that is not to 'const' cannot be bound to a
non-lvalue

Again Good news (dam that we ported 7.0 and not 7.1). Also there where more
indirections in the actual code then in this simplified example. After all
it was all done for a container class template.

Martin
 
I

Ioannis Vranos

Some interesting news regarding .NET support by another language (from WinInfo Daily
Update newsletter):



Python Expands To IronPython

You might have heard of Python, a popular and powerful cross-
platform open-source programming language. Python, which is the
creation of Jim Hugunin, is described as "an interpreted, interactive,
object-oriented programming language ... often compared to Java, Perl,
Scheme, or Tcl." The basic description says a lot (for more information
about Python, see the URL below). Even behemoths such as Google rely
heavily on Python to develop their solutions. Microsoft has also
recently gotten into the act.
http://list.windowsitpro.com/t?ctl=6431:275FF
Last year, Hugunin decide to expand on Python by creating IronPython
(see the first URL below), a new implementation that works within the
Microsoft .NET Framework and the cross-platform Mono environment, which
Novell sponsors (see the second URL below). Version 0.6 was released to
the public in July, when Hugunin also announced that he was joining
Microsoft to continue working on IronPython's evolution. Last week
(some 8 months after Hugunin joined the company), Microsoft released
IronPython pre-alpha version 0.7 to the public. Incidentally, Microsoft
stresses on its download page that IronPython is a codename, so
undoubtedly the company plans to come up with another name for the
final release.
http://list.windowsitpro.com/t?ctl=6430:275FF
http://list.windowsitpro.com/t?ctl=642F:275FF
IronPython is faster than the original Python and lets programmers
handle diverse sets of styles, interfaces, and subsystems. You can also
use the language to communicate with hardware and to develop the same
functionality as programs written in other languages--but with far
fewer lines of code. With IronPython, you can also produce static
runtime executables (.exe files) and DLLs.
The main thrust of IronPython seems to be that it supports
Microsoft's Common Language Runtime (CLR) environment (see the first
URL below), which allows seamless integration of code written in
numerous languages, such as C++, C#, Java, and Visual Basic (VB). If
you want a flexible cross-platform language, be sure to check out
Python, and if you're developing for .NET Framework, you should
certainly check out IronPython 0.7 (see the second URL below).
IronPython also has a message board, documentation, and a bug-tracking
facility (see the third URL below) and a mailing list you can join (see
the fourth URL below), although Hugunin implied in a message to the
list that it might eventually be closed in favor of the message board.
http://list.windowsitpro.com/t?ctl=642A:275FF
http://list.windowsitpro.com/t?ctl=6423:275FF
http://list.windowsitpro.com/t?ctl=6426:275FF
http://list.windowsitpro.com/t?ctl=6427:275FF
 
D

Dave Thompson

PL/I. And (no surprise) it includes nearly everything.

COBOL supports pre-compile token sequence(!) replacement, like a very
weak type-1 language, as well as file-ish inclusion, which is so
common it's arguable whether it's really preprocessing. I've heard in
the 2002 revision they added some more but I haven't looked yet.

Fortran officially has an option for conditional compilation and file
inclusion, 1539-3. At least before the "2003" revision -- I don't see
a new one. But -3 doesn't seem to be widely implemented or used;
Fortran programmers who need preprocessing at all seem mostly to make
do with cpp, or m4 or such, or write custom.

(Also there are bindings/embeddings for SQL that are typically
implemented by preprocessors, but I'm not sure they're standard, and
anyway that's not a preprocessor _for the language_.)
Lisp macros are _not_ a preprocessor and they are _vastly_ more
capable than what people typically think of when they see/hear
"macros". Lisp macros are full code analyzing and generating
constructs. Things like C/C++ preprocessor/"macro" simplistic text
substitutions are not in any way related to them. <snip>

They're not just text (really lexeme) substitution, and are much more
powerful, yes. But they transform the code as written before
compilation, and to me that is the definition of _a_ preprocessor.

It depends on who is 'hearing' 'macro': C/C++ macros are quite weak,
but some of the classic macro assemblers like S/360 and PDP-10 are
pretty powerful, and I would say TECO and TEX and maybe some of the
other text formatters like SCRIBE come close to Lisp in functionality
though not remotely in clarity and usability.

- David.Thompson1 at worldnet.att.net
 
D

Dave Thompson

In C++ you can always do:
void somefunc()
{
unsigned char obj[sizeof(SomeClass)];
In addition to the alignment problem, which can be more or less hacked
around, that's not 'indefinite' (runtime) size, which is what alloca
is good for, and was exactly the snipped question I was answering.

SomeClass *somefunc()
{
static unsigned char obj[sizeof(SomeClass)];

return new(obj)SomeClass;
}


int main()
{
SomeClass *p= somefunc();

delete p;
}


Here the object is created in the stack.

No it's not, it's static. And if it was it wouldn't survive the return
from somefunc, exactly the same issue I said occurs with alloca().

And it still wouldn't be variable size; C++ has no _declared_ (stack
or static) variable size items. It does have _pointers_ and
_references_ to differing and/or varying type (within hierarchy) or
size items; that's not the same thing. As long as we're at it, C99
(and GNU89) has Variable Length Arrays, only within a scope thus
including a subblock but not returned, and Flexible Array Members
which only access but don't allocate variable size.

To stack-allocate and/or return a fixed-size aggregate, you don't need
any such shenanigans, just use a C struct or a C++ copyable class.

- David.Thompson1 at worldnet.att.net
 
A

Adrien Plisson

Ioannis said:
Some interesting news regarding .NET support by another language (from
WinInfo Daily Update newsletter):

where do they get their info from ???
You might have heard of Python, a popular and powerful cross-
platform open-source programming language. Python, which is the
creation of Jim Hugunin, [...]

Python is the creation of Guido van Rossum at Stichting Mathematisch
Centrum (CWI <http://www.cwi.nl/>) in the Netherlands !
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,135
Latest member
VeronaShap
Top