strange runtime behaviour with gcc

L

Levent

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.
 
T

Teddy

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
 
P

Peter Julian

Levent said:
Hi,

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

Well, then give gcc the prize becuse the other compilers failed the task.
#include <iostream>

class Foo {
public:
typedef int subs[3];

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.

int main()
{
int sz[]={10,20,30};

Why aren't you encapsulating the array container? Why bother write the
classes Foo and Bar otherwise?
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.

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 << 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.
 
O

Old Wolf

Peter said:
A compiler that allows ...

typedef int subs[3];

... is allowing undefined behaviour.

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

Pete Becker

Peter said:
Well, then give gcc the prize becuse the other compilers failed the task.

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.
#include <iostream>

class Foo {
public:
typedef int subs[3];


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.

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

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,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top