473,413 Members | 1,705 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,413 software developers and data experts.

how to improve custom String implementation

Dev
Hello,

In the following class definition,
the ZString destructor is invoked two times.
This crashes the code.

class ZString
{
public:
ZString(char* p)
: _sz(::strlen(p)),
_p(new char[_sz+1])
{
::strcpy(_p,p);
}

~ZString()
{
delete [] _p;
}

char& operator [] (int i)
{
return _p[i];
}

private:
int _sz;
char* _p;
};
int main(int argc, char* argv[])
{
ZString s1("John");
ZString s2 = s1;

return 0;
}

An immediate solution that comes to my mind is to provide
the implementation of the assignment operator, wherein a
new ZString object is created using the field values from the
existing ZString object (rhs).

Can anybody suggest better approaches to improve the class
implementation, with trade offs ?

Thanks in advance.

Dev.

Sep 15 '05 #1
7 2684
Dev wrote:
Hello,

In the following class definition,
the ZString destructor is invoked two times.
Well, there are two ZString objects. Each of them gets constructed and each
of them gets destroyed.
This crashes the code.

class ZString
{
public:
ZString(char* p)
: _sz(::strlen(p)),
_p(new char[_sz+1])
{
::strcpy(_p,p);
}

~ZString()
{
delete [] _p;
}

char& operator [] (int i)
{
return _p[i];
}

private:
int _sz;
char* _p;
};
int main(int argc, char* argv[])
{
ZString s1("John");
ZString s2 = s1;

return 0;
}

An immediate solution that comes to my mind is to provide
the implementation of the assignment operator, wherein a
new ZString object is created using the field values from the
existing ZString object (rhs).
In your code, the assignment operator is not involved, but rather the copy
constructor. An assignment operator takes an existing objects and replaces
its value with that of an other object.
Can anybody suggest better approaches to improve the class
implementation, with trade offs ?


No, the implementation of an assignment operator and a copy constructor is
exactly what you need. Both of them get automatically created by the
compiler if you don't provide your own implementation. Those just do a
memberwise copy, which in your case is not what you want.
The problem is that the second object gets created through the copy
constructor. The pointer member gets copied, so both objects' pointers
point to the same memory location. When one of your objects is destroyed,
the memory gets freed, but the other object still expects the pointer to be
valid.
So you need to provide your own implementation that does The Right
Thing(tm).
There is a rule called the Rule of Three that says: If you need one of a
copy constructor, assignment operator and destructor, you probably (almost
definitely) need all three of them.
You just found out the reason for that rule.

Sep 15 '05 #2
Yup.. they are right.. You need one of these

ZString(const ZString& s)
: _sz(s._sz),
_p(new char[_sz+1])
{
::strcpy(_p,s._p);
}

Sep 15 '05 #3
Dev wrote:
Hello,

In the following class definition,
the ZString destructor is invoked two times.
This crashes the code.

class ZString
{
public:
ZString(char* p)
: _sz(::strlen(p)),
_p(new char[_sz+1])
{
::strcpy(_p,p);
}

~ZString()
{
delete [] _p;
}

char& operator [] (int i)
{
return _p[i];
}

private:
int _sz;
char* _p;
};
int main(int argc, char* argv[])
{
ZString s1("John");
ZString s2 = s1;

return 0;
}

An immediate solution that comes to my mind is to provide
the implementation of the assignment operator, wherein a
new ZString object is created using the field values from the
existing ZString object (rhs).

Can anybody suggest better approaches to improve the class
implementation, with trade offs ?

Thanks in advance.

Dev.


If you haven't defined a copy constructor, the compiler does this for
you. The problem is that it does a shallow copy, so both your objects
have the same address for the _p pointer. When your main() returns, it
deallocates __p for each object, and thus causing a double free. You
have to define the copy constructor where you explicitly allocate
memory for _p and do a strcpy.

Sep 15 '05 #4
Dev
Dev wrote:
Hello,

In the following class definition,
the ZString destructor is invoked two times.
This crashes the code.

class ZString
{
public:
ZString(char* p)
: _sz(::strlen(p)),
_p(new char[_sz+1])
{
::strcpy(_p,p);
}
I added an copy constructor here.


int main(int argc, char* argv[])
{
ZString s1("John");
ZString s2 = s1;

return 0;
}


Additionally, I set s1 = 0
immediately after construction of s2.

Now, I get a Segmentation Fault.

Is there a way to get around this problem ?

thanks
Dev.

Sep 16 '05 #5
Dev wrote:
Dev wrote:
Hello,

In the following class definition,
the ZString destructor is invoked two times.
This crashes the code.

class ZString
{
public:
ZString(char* p)
: _sz(::strlen(p)),
_p(new char[_sz+1])
{
::strcpy(_p,p);
}


I added an copy constructor here.
int main(int argc, char* argv[])
{
ZString s1("John");
ZString s2 = s1;

return 0;
}

Additionally, I set s1 = 0
immediately after construction of s2.

Now, I get a Segmentation Fault.

Is there a way to get around this problem ?


Of course, what sort of language do you think C++ is?

You should stop focussing on the two calls to the destructor, that is
correct, it is what happens before that that is incorrect. Since you
haven't posted the copy constructor you wrote I would expect that the
error is there.

You are also missing an operator= for you class, which is essential in
the long run, but should not be causeing the problems above. It's a
common situation in C++ that when yu program crashes, it not the code at
the point it crashes that is wrong but the code somwhere before where it
crashes.

I don't understand what you mean by 'Additionally, I set s1 = 0' does
that mean that you program was literally like this

int main(int argc, char* argv[])
{
ZString s1("John");
ZString s2 = s1;
s1 = 0;
return 0;
}

If that is the case, then I don't understand why you are surprised you
got a crash. It's an obvious null pointer error.

Here is a working ZString class and program. The main changes from you
code are the addition of const in the appropriate places, a working
assignment operator and copy constructor and a const version of
operator[]. All these things are necessary for a simple string class.

#include <cstring>
#include <algorithm>

class ZString
{
public:
ZString(const char* p)
: _sz(::strlen(p)),
_p(new char[_sz+1])
{
::strcpy(_p,p);
}

ZString(const ZString& rhs)
: _sz(::strlen(rhs._p)),
_p(new char[_sz+1])
{
::strcpy(_p, rhs._p);
}

void swap(ZString& rhs)
{
std::swap(_sz, rhs._sz);
std::swap(_p, rhs._p);
}

ZString& operator=(const ZString& rhs)
{
ZString tmp(rhs);
swap(tmp);
return *this;
}

~ZString()
{
delete [] _p;
}

char& operator [] (int i)
{
return _p[i];
}

char operator [] (int i) const
{
return _p[i];
}

private:
int _sz;
char* _p;
};
int main(int argc, char* argv[])
{
ZString s1("John");
ZString s2 = s1;

return 0;
}

john
Sep 16 '05 #6
John Harrison wrote:
I don't understand what you mean by 'Additionally, I set s1 = 0' does
that mean that you program was literally like this

int main(int argc, char* argv[])
{
ZString s1("John");
ZString s2 = s1;
s1 = 0;
return 0;
}

If that is the case, then I don't understand why you are surprised you
got a crash. It's an obvious null pointer error.

[] class ZString
{
public:
ZString(const char* p)
Watch out for a passed a 0 pointer as the OP did
: _sz(::strlen(p)),
_p(new char[_sz+1])
{
::strcpy(_p,p);
}


--
Karl Heinz Buchegger
kb******@gascad.at
Sep 16 '05 #7
Karl Heinz Buchegger wrote:
John Harrison wrote:
>

I don't understand what you mean by 'Additionally, I set s1 = 0' does
that mean that you program was literally like this

int main(int argc, char* argv[])
{
ZString s1("John");
ZString s2 = s1;
s1 = 0;
return 0;
}

If that is the case, then I don't understand why you are surprised you
got a crash. It's an obvious null pointer error.

[]
class ZString
{
public:
ZString(const char* p)


Watch out for a passed a 0 pointer as the OP did
: _sz(::strlen(p)),
_p(new char[_sz+1])
{
::strcpy(_p,p);
}


For example like this:

ZString(const char* p)
: sz_(p ? std::strlen(p) : 0),
p_(new char[sz_+1])
{
if (p)
std::memcpy(p_,p, sz_);
else
*p_ = '\0';
}

I chose trailing undescores, because they are not reserved, I used the
functions from the std namespace, because they are supposed to be
preferred, and I used memcpy instead of strcpy, because that might be a bit
faster and has no disadvantage.

Sep 16 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: Matt Garman | last post by:
I'd like to create a "custom output facility". In other words, I want an object whose use is similar to std::cout/std::cerr, but offers more flexibility. Instead of simply writing the parameter...
9
by: Peng Jian | last post by:
I have a function that is called very very often. Can I improve its efficiency by declaring its local variables to be static?
1
by: Martin | last post by:
Hi, I have produced a custom server control that simple outputs a row of 26 buttons, one button for each letter of the english alphabet. now what I would like to do is catch the button click...
5
by: mtv | last post by:
Hi all, I have the following code: ================================ Webservice side: public class MyWS: WebService { private myLib.DataObject curDataObject;
0
by: webmaster | last post by:
Hi all, I'm tearing my hair out with this one. I have successfully implemented by own RadioButtonList in order to provide additional functionality and a DIV rather than TABLE-based layout in...
4
by: Val | last post by:
I have a complex object that I need to serialize. Rather than rely on a standard routine, which is called during the serialization/deserialization, I would like to be able to use my own functions...
11
by: Peted | last post by:
Im using c# 2005 express edition Ive pretty much finished an winforms application and i need to significantly improve the visual appeal of the interface. Im totaly stuck on this and cant seem...
11
by: =?Utf-8?B?bWljaGFlbCBzb3JlbnM=?= | last post by:
I have worked with application settings in VS2005 and C# for awhile, but usually with standard types. I have been trying to store a custom container/class/type in an application setting and I have...
1
by: asharda | last post by:
I have a custom property grid. I am using custom property grid as I do not want the error messages that the propertygrid shows when abphabets are entered in interger fields. The custom property...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.