Connecting Tech Pros Worldwide Forums | Help | Site Map

strange runtime behaviour with gcc

Levent
Guest
 
Posts: n/a
#1: Jul 23 '05
Hi,

When compiled with gcc 3.3.3 and lower on various systems (tried cygwin,
linux, aix) the following code behaves strangely:

#include <iostream>

class Foo {
public:
typedef int subs[3];
void callme(subs s)
{
std::cout << s[2] << std::endl;
}
};

template<class foo_type>
class Bar
{
public:
void callme(typename foo_type::subs s)
{
std::cout << s[2] << std::endl;
}
};

int main()
{
int sz[]={10,20,30};
Foo f;
f.callme(sz); // should print 30 and it does
Bar<Foo> b;
b.callme(sz); // should print 30 but it does not with gcc
return 0;
}

The problem is that `Bar<Foo>::callme' somehow accesses uninitized space
in memory instead of the one sz[] points to. This is not the case with
any other compiler I had access to (visual c++ 7.1, visualage 6, intel
7 and 8).

Does the above code have semantic problems, or is this just a gcc-bug
(in which case I apologize for this gcc specific and thus off-topic(ish)
thread)?

- L.





Teddy
Guest
 
Posts: n/a
#2: Jul 23 '05

re: strange runtime behaviour with gcc


the code works well on my gcc 3.3.3 after i made the modification
below:
class Foo {
public:
typedef int* subs; //modification here
void callme(subs s)
{
std::cout << s[2] << std::endl;
}
};

interesting , and i want to why

Peter Julian
Guest
 
Posts: n/a
#3: Jul 23 '05

re: strange runtime behaviour with gcc



"Levent" <sly5@pitt.edu> wrote in message
news:d7k99h$391$1@usenet01.srv.cis.pitt.edu...[color=blue]
> Hi,
>
> When compiled with gcc 3.3.3 and lower on various systems (tried cygwin,
> linux, aix) the following code behaves strangely:[/color]

Well, then give gcc the prize becuse the other compilers failed the task.
[color=blue]
>
> #include <iostream>
>
> class Foo {
> public:
> typedef int subs[3];[/color]

undefined behaviour, an array object is not an integer nor can it ever be.
typedef is meant to create a new type definition, not to act like a pointee
converter.

<snip>
[color=blue]
> int main()
> {
> int sz[]={10,20,30};[/color]

Why aren't you encapsulating the array container? Why bother write the
classes Foo and Bar otherwise?
[color=blue]
> Foo f;
> f.callme(sz); // should print 30 and it does
> Bar<Foo> b;
> b.callme(sz); // should print 30 but it does not with gcc
> return 0;
> }
>
> The problem is that `Bar<Foo>::callme' somehow accesses uninitized space
> in memory instead of the one sz[] points to.[/color]

Because subs is passed as an integer to Bar<Foo>callme's parameter, subs is
not an array. A compiler that allows ...

typedef int subs[3];

.... is allowing undefined behaviour. C++ implies strict type checking, not a
particular compiler's version of type redefinitions.

Try the code below in all compilers mentioned above:
Note that an array is not the appropriate container here. A vector would
have been more usefull. Foo's constructor initializes the array's elements.
The member functions callme() only need a reference to the container's
index.

The array is a private member of the Foo type, and the Bar type is
*composed* of a templated member that must support the callme() member
function.

#include <iostream>

class Foo
{
int subs[3];
public:
Foo()
{
std::cout << "Foo ctor invoked\n";
subs[0] = 10;
subs[1] = 20;
subs[2] = 30;
}
void callme(const int& i) const
{
std::cout << subs[i] << std::endl;
}
};

template<class foo_type>
class Bar
{
foo_type t;
public:
Bar() : t() { std::cout << "Bar ctor invoked\n"; }
void callme(const int& i) const
{
t.callme(i);
}
};

int main()
{
Foo f;
f.callme(2); // should print 30

Bar<Foo> b;
b.callme(2); // should print 30

return 0;
}

/* output:

Foo ctor invoked
30
Foo ctor invoked
Bar ctor invoked
30

*/

A vector is a much better choice than an array. Also, if Foo and Bar are
meant to have an "is_a" relationship (a Bar is_a Foo, a Car is_a Vehicle, a
Circle is_a shape), then you should have Bar inherit from Foo instead.

Old Wolf
Guest
 
Posts: n/a
#4: Jul 23 '05

re: strange runtime behaviour with gcc


Peter Julian wrote:[color=blue]
>
> A compiler that allows ...
>
> typedef int subs[3];
>
> ... is allowing undefined behaviour.[/color]

Please review your C++ textbook. That code is correct and
declares that 'subs' is an alias for an array of 3 ints.

Pete Becker
Guest
 
Posts: n/a
#5: Jul 23 '05

re: strange runtime behaviour with gcc


Peter Julian wrote:[color=blue]
> "Levent" <sly5@pitt.edu> wrote in message
> news:d7k99h$391$1@usenet01.srv.cis.pitt.edu...
>[color=green]
>>Hi,
>>
>>When compiled with gcc 3.3.3 and lower on various systems (tried cygwin,
>>linux, aix) the following code behaves strangely:[/color]
>
>
> Well, then give gcc the prize becuse the other compilers failed the task.
>[/color]

If you were right that the behavior of this code is undefined, it
wouldn't follow that any compiler failed in any way. Undefined behavior
is simply undefined. The language definition does not require any
particular behavior, so anything a compiler does is okay.
[color=blue]
>[color=green]
>>#include <iostream>
>>
>>class Foo {
>>public:
>> typedef int subs[3];[/color]
>
>
> undefined behaviour, an array object is not an integer nor can it ever be.
> typedef is meant to create a new type definition, not to act like a pointee
> converter.
>[/color]

The typedef says that 'subs' is an array of 3 ints.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Levent
Guest
 
Posts: n/a
#6: Jul 23 '05

re: strange runtime behaviour with gcc


Teddy wrote:
[color=blue]
>interesting , and i want to why
>
>
>[/color]
I just found out that this is a bug in gcc which is fixed in the new
release, 4.0.0:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20208

Closed Thread