a=b does not screw up like it used to do!

G

Gandalf

Hello.
My code is appended at the bottom of this posting. It's a simple class
using a char* as only datamember.
The problem is the very strange result I get on Windows 98 with the latest
DevC++ 4.9.8.1 compared to Linux (Debian 3.0) g++ -version 2.95.4

So, what is the problem then? The problem is "why do I get different output
from my program?" Has there been changes in the C++ standard for handling
char* pointers or is the compiler more (stupid/smarter???)
Could someone tell me?


Result with Linux

Gandalf
Vidstige
Sauron
Sauron // as expected!
à
à // as expected.
Legolas
Legolas
Bilbo
Bilbo

Result with Windows

Gandalf
Vidstige
Sauron
Gandalf
Gandalf
Sauron
Legolas
Gandalf
Bilbo
Gandalf


----------------------------------
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
class Problem {
private:
char* text;
public:
Problem() {text=new char[1]; *text='\0';}
~Problem() {delete[] text;}
void Skriv(){cout <<text<<endl;}
void Set(char* str) {delete[] text; text=new char[strlen(str)+1];
strcpy(text,str);}
};
void testref(Problem& x){
x.Set("Bilbo");
x.Skriv();
}
void test(Problem x){
x.Set("Bilbo");
x.Skriv();
}

int main() {
Problem a;
Problem b;
a.Set("Gandalf");
b.Set("Vidstige");
a.Skriv();
b.Skriv(); // everything is ok
b=a; // NOTICE THIS!

a.Set("Sauron");
a.Skriv();
b.Skriv();

test(b);
b.Skriv();
a.Skriv();
a.Set("Legolas");
a.Skriv();
b.Skriv();
testref(a);
a.Skriv();
b.Skriv();
getchar();
}
 
R

Ron Natalie

Gandalf said:
So, what is the problem then? The problem is "why do I get different output
from my program?" Has there been changes in the C++ standard for handling
char* pointers or is the compiler more (stupid/smarter???)

The problem is that your class is defective. Their is a so-called rule-of-three
that says: "If you need a copy constructor, copy-assignment operator, or destructor,
then you probably need all three."

What is happening is that the variable text you are managing gets messed up
if you assign the variables to each other. The left hand of the assignement
loses it's value and the right hand value gets left in both sides. This just
leads to confusion, and the issue that the same storage is deleted twice
or used after deleted.

You need to add a copy constructor and a copy-assignment operator to
make copies (and in the case of assignment, delete the previous vailue).
Similar to what your Set() function does.

However, all this nonsense would be avoided if you stop using char* as
a string type (WHICH IT IS NOT!).

class Problem {
private:
string text;
public:
void Skriv() const { cout << text << "\n"; }
void Set(const std::string& str) { text = str; }
};

Notice how much easier the above is. Set becomes much more trivial and
the coimpiler generated default constructor, destructor, copy constructor, and copy-assignment
operator work just fine because the string object implements those functoins
itself.
 
V

Victor Bazarov

Gandalf said:
My code is appended at the bottom of this posting. It's a simple class
using a char* as only datamember.
The problem is the very strange result I get on Windows 98 with the latest
DevC++ 4.9.8.1 compared to Linux (Debian 3.0) g++ -version 2.95.4

So, what is the problem then? The problem is "why do I get different output
from my program?" Has there been changes in the C++ standard for handling
char* pointers or is the compiler more (stupid/smarter???)
Could someone tell me?

You are missing a copy constructor and the copy assignment operator
in your Problem class. Read about "The Rule of Three".
Result with Linux

Gandalf
Vidstige
Sauron
Sauron // as expected!
à
à // as expected.
Legolas
Legolas
Bilbo
Bilbo

Result with Windows

Gandalf
Vidstige
Sauron
Gandalf
Gandalf
Sauron
Legolas
Gandalf
Bilbo
Gandalf


----------------------------------
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
class Problem {
private:
char* text;
public:
Problem() {text=new char[1]; *text='\0';}
~Problem() {delete[] text;}
void Skriv(){cout <<text<<endl;}
void Set(char* str) {delete[] text; text=new char[strlen(str)+1];
strcpy(text,str);}
};
void testref(Problem& x){
x.Set("Bilbo");
x.Skriv();
}
void test(Problem x){
x.Set("Bilbo");
x.Skriv();
}

int main() {
Problem a;
Problem b;
a.Set("Gandalf");
b.Set("Vidstige");
a.Skriv();
b.Skriv(); // everything is ok
b=a; // NOTICE THIS!

a.Set("Sauron");
a.Skriv();
b.Skriv();

test(b);
b.Skriv();
a.Skriv();
a.Set("Legolas");
a.Skriv();
b.Skriv();
testref(a);
a.Skriv();
b.Skriv();
getchar();
}
 
M

Mike Wahler

Gandalf said:
Hello.
My code is appended at the bottom of this posting. It's a simple class
using a char* as only datamember.
The problem is the very strange result I get on Windows 98 with the latest
DevC++ 4.9.8.1 compared to Linux (Debian 3.0) g++ -version 2.95.4

So, what is the problem then? The problem is "why do I get different output
from my program?" Has there been changes in the C++ standard for handling
char* pointers or is the compiler more (stupid/smarter???)
Could someone tell me?

You need a copy constructor and copy assignment operator
for your 'Problem' class. Look up 'rule of three'.

Your program has memory leaks and undefined behavior.

-Mike
 
G

Gianni Mariani

Gandalf said:
Hello.
My code is appended at the bottom of this posting. It's a simple class
using a char* as only datamember.
The problem is the very strange result I get on Windows 98 with the latest
DevC++ 4.9.8.1 compared to Linux (Debian 3.0) g++ -version 2.95.4

So, what is the problem then? The problem is "why do I get different output
from my program?" Has there been changes in the C++ standard for handling
char* pointers or is the compiler more (stupid/smarter???)
Could someone tell me?

The program operation is undefined because the assignment operator does
not do the right thing.

You are accessing a char * after deleting it. The operation is
undefined and most likely random.

....
----------------------------------
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
class Problem {
private:
char* text;
public:
Problem() {text=new char[1]; *text='\0';}
~Problem() {delete[] text;}
void Skriv(){cout <<text<<endl;}
void Set(char* str) {delete[] text; text=new char[strlen(str)+1];
strcpy(text,str);}
};
void testref(Problem& x){
x.Set("Bilbo");
x.Skriv();
}
void test(Problem x){
x.Set("Bilbo");
x.Skriv();
}

int main() {
Problem a;
Problem b;
a.Set("Gandalf");
b.Set("Vidstige");
a.Skriv();
b.Skriv(); // everything is ok
b=a; // NOTICE THIS!
^^^^^^^^^^^^^^^^^^^ this leaks the string in b
a.Set("Sauron");
^^^^^^^^^^^^^^^^^^^ This deletes the string in n and sets a new one in a.
a.Skriv();
b.Skriv();
^^^^^^^^^^^^^^^^^^^ UNDEFINED - uses deleted string
^^^^^^^^^^^^^^^^^^^ Deletes the string in b TWICE - bad bad bad -
everything from here on is undefined.

I ran valgrind on this code and it screams all kinds of probs.

Use std::string ...
 
T

tom_usenet

Hello.
My code is appended at the bottom of this posting. It's a simple class
using a char* as only datamember.
The problem is the very strange result I get on Windows 98 with the latest
DevC++ 4.9.8.1 compared to Linux (Debian 3.0) g++ -version 2.95.4

So, what is the problem then? The problem is "why do I get different output
from my program?" Has there been changes in the C++ standard for handling
char* pointers or is the compiler more (stupid/smarter???)
Could someone tell me?

Your program contains some undefined behaviour - you access some
memory you've already deleted. When you do this, anything can happen,
such as displaying an accented a character or the word "Gandalf" -
neither is "correct" behaviour, since you shouldn't really be
expecting any particular behaviour.
Result with Linux

Gandalf
Vidstige
Sauron
Sauron // as expected!
à
à // as expected.
Legolas
Legolas
Bilbo
Bilbo

Result with Windows

Gandalf
Vidstige
Sauron
Gandalf
Gandalf
Sauron
Legolas
Gandalf
Bilbo
Gandalf


----------------------------------
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
class Problem {
private:
char* text;
public:
Problem() {text=new char[1]; *text='\0';}
~Problem() {delete[] text;}
void Skriv(){cout <<text<<endl;}
void Set(char* str) {delete[] text; text=new char[strlen(str)+1];
strcpy(text,str);}
};
void testref(Problem& x){
x.Set("Bilbo");
x.Skriv();
}
void test(Problem x){
x.Set("Bilbo");
x.Skriv();
}

int main() {
Problem a;
Problem b;
a.Set("Gandalf");
b.Set("Vidstige");
a.Skriv();
b.Skriv(); // everything is ok
b=a; // NOTICE THIS!

Now a.text and b.text point to the same string.
a.Set("Sauron");

Here you've deleted a.text (and therefore b.text), and set a.text to
"Sauron". So far nothing illegal.
a.Skriv();

This displays "Sauron".
b.Skriv();

Oh dear - you've deleted b.text and now you've tried to display it.
This is undefined behaviour - from this point on, your program might
do anything (crash, display garbage, whatever).

As others have said, you need to write a correct copy constructor and
assignment operator.

Tom
 
J

jeffc

Ron Natalie said:
However, all this nonsense would be avoided if you stop using char* as
a string type (WHICH IT IS NOT!).

I do not understand why C++ programmers persist in using char* when it's not
necessary.
 
D

Default User

jeffc said:
I do not understand why C++ programmers persist in using char* when it's not
necessary.

Mostly due to finding code examples on the web and in older, outdated
texts.




Brian Rodenborn
 
K

Kevin Goodsell

Default said:
jeffc wrote:




Mostly due to finding code examples on the web and in older, outdated
texts.

The problem is deeper than that, I think. Not just old texts and bad web
examples, but

* Teachers that don't update their material
* NEW textbooks that ignore or nearly ignore modern C++
* A high volume of code and a large number of "C++ programmers" that use
the old methods.

A new C++ programmer is basically immersed in old-style C++. Modern C++
gets alluded to occasionally, but seems mysterious and frightening to
the newbie. This is partly because the syntax and types aren't
immediately familiar, but also because of the way books, teachers, etc.
only mention it in passing, and seem to treat it like black magic.

-Kevin
 
J

jeffc

Kevin Goodsell said:
The problem is deeper than that, I think. Not just old texts and bad web
examples, but

* Teachers that don't update their material
* NEW textbooks that ignore or nearly ignore modern C++
* A high volume of code and a large number of "C++ programmers" that use
the old methods.

A new C++ programmer is basically immersed in old-style C++. Modern C++
gets alluded to occasionally, but seems mysterious and frightening to
the newbie.

Gosh, I was just the opposite. char* is frightening to me, and I couldn't
wait to start writing in a language with a usable string type. I don't
think I've seen any single "tactic" (or "design element" or whatever you
want to call it) cause more bugs than char*.
 
W

White Wolf

jeffc wrote:
[SNIP]
Gosh, I was just the opposite. char* is frightening to me, and I
couldn't wait to start writing in a language with a usable string
type. I don't think I've seen any single "tactic" (or "design
element" or whatever you want to call it) cause more bugs than char*.

Buffer overruns. Need we say more? Of course arrays (be it character array
or something else) will be and are a fundamental building block of every
software on todays computer architecture - even if they are hidden in a
virtual machine. However this does not mean that we are not going to hide
them as much as possible also in C++. :) Pointers (especially pointer
arithmentics) belong into (standard or in-house) libraries forming the
elements used by the higher level design - the business logic. In my "dream
world" the business logic (in C++ or any language) is programmed using
objects representing concepts of the problems domain and no pointers in
sight! ;-)
 
G

Gavin Deane

White Wolf said:
In my "dream world" the business logic (in C++ or any language) is programmed > using objects representing concepts of the problems domain and no pointers in
sight! ;-)

What a shame it is that even today that is still a dream world and not
a widespread reality. I am not saying that highly abstract OOP, with
no concern for how the computer that runs the program actually works,
is relevant for everything. But it is appropriate in far more cases
than it is used.
 
A

Attila Feher

Gavin said:
What a shame it is that even today that is still a dream world and not
a widespread reality. I am not saying that highly abstract OOP, with
no concern for how the computer that runs the program actually works,
is relevant for everything. But it is appropriate in far more cases
than it is used.

IMHO many successful languages (SQL, CA-Clipper, Python), some general
purpose, some special, did base their philosophy on those rules.
 

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,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top