Thread: String Class

  1. #61
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    Quote Originally Posted by vart View Post
    1. stringlength member may be not initialized or initialized not properly
    2. temp is pointing to the not initialized buffer buf
    3. strcpy(buf, temp); has no effect - you copying buffer over itself (maybe you think you copy the old buffer contents - but you effectively lost it making memory leak)
    4. strcat(buf, str.buf); - you appending to not initialized buffer - behavior is undefined
    5. delete []temp; - you deleting newly allocated buffer leaving your object in the dengerous state
    do I even need temp?

  2. #62
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    yes - you need it... but you need to allocate buffer into temp, copy there all the resulting string
    and (if successful)
    free the original buffer and point the buf pointer to the temp where the new string is stored

    in this case - if something failes - the original string will be untoched
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  3. #63
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    Are there any memory leaks with this code? Does size need to be bigger?

    Code:
    String& String::operator +=(const String & str)
    {
    	int newsize = getLength() + str.getLength();
    	stringlength = newsize;
    	size =  newsize + 1;
    	char *temp = buf;
    	buf = new char[size];
    	strcpy(buf, temp);
    	strcpy(buf + getLength(), str.buf);
    	return *this;
    }

  4. #64
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Are there any memory leaks with this code
    Yes. You do not delete the old buffer

    strcpy(buf + getLength(),
    getLength returns stringlength wich already points to newsize index...
    So you writing outside the allocated buffer
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  5. #65
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    SOB. I just wrote to help in another thread only to find you've also got this thread going about the problem already where people have mentioned what I just did.

    DON'T EFFING DO THAT!
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  6. #66
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    Quote Originally Posted by vart View Post
    Yes. You do not delete the old buffer


    getLength returns stringlength wich already points to newsize index...
    So you writing outside the allocated buffer
    I managed to change the code to look like this, but there are still problems with it:

    Code:
    String& String::operator +=(const String & str)
    {
    	int newsize = getLength() + str.getLength();
    	size =  newsize + 1;
    	char *temp = new char[size];
    	assert(temp != 0);
    	strcpy(temp, buf);
    	delete []buf;
    	buf = temp;
    	strcat(buf + getLength(), str.buf);
    	stringlength = newsize;
    	return *this;
    }

  7. #67
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    strcat(buf + getLength(), str.buf);
    should be
    strcat(buf, str.buf);
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  8. #68
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    Quote Originally Posted by vart View Post
    strcat(buf + getLength(), str.buf);
    should be
    strcat(buf, str.buf);
    Now there is a break at strcat(buf, str.buf);

  9. #69
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    And you have exemined the variables at this point and found that...
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  10. #70
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    Quote Originally Posted by vart View Post
    And you have exemined the variables at this point and found that...
    I ran the debugger line by line and it seemed to be running fine then all of a sudden buf and temp went from ABCD to ABCDABCDABCDABCD and it never ends and a break pops up that says:
    Unhandled exception at 0x102aece9 in String Lab.exe: 0xC0000005: Access violation writing location 0x00359000.

  11. #71
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    Does anybody see anything wrong with my +operators:

    Code:
    String operator +(const String& lhs, const String& rhs)
    {
    	String result(lhs);
    	result += rhs;
    	return result;
    }
    
    String operator +(char str, const String& rhs)
    {
    	String result;
    	result = str;
    	result += rhs;
    	return result;
    }
    
    String operator +(const String& rhs, char str)
    {
    	String result(rhs);
    	result += str;
    	return result;
    }
    
    String operator +(const char* str, const String& rhs)
    {
    	String result;
    	result = str;
    	result += rhs;
    	return result;
    }
    
    String operator +(const String& rhs, const char* str)
    {
    	String result(rhs);
    	result += str;
    	return result;
    }

  12. #72
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Provided that the constructor and operator overloads you use there are correct, these look OK.

    If you have constructors that take a single character or char* you might use it and omit the assignment step.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  13. #73
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Have you fixed all of your constructors?

  14. #74
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    Quote Originally Posted by Daved View Post
    Have you fixed all of your constructors?
    I think they all work but Ill post my code below and if you see anything then please tell me.

    Code:
    //string.h
    
    #ifndef String_H
    #define String_H
    
    #include <iostream>
    #include "strdrv.h"
    using namespace std;
    
    class String
    {
    	friend String operator+(const String& lhs, const String& rhs);
    	friend String operator+(const String& rhs, const char* str);
    	friend String operator+(const char* str, const String& rhs);
    	friend String operator+(const String& rhs, char str);
    	friend String operator+(char str, const String& rhs);
    	friend int operator==(const String& lhs, const String& rhs);
    	friend int operator!=(const String& lhs, const String& rhs);
    	friend int operator< (const String& lhs, const String& rhs);
    	friend int operator<=(const String& lhs, const String& rhs);
    	friend int operator> (const String& lhs, const String& rhs);
    	friend int operator>=(const String& lhs, const String& rhs);
    	friend char* operator+(const String &rhs, int element);
    	friend char* operator+(int element, const String &rhs);
    	friend ostream& operator<<(ostream&, const String&);
    
    public:
    	String();
    	String(const char* str);
    	String(char nme);
    	String(int sizeofstring);
    	String(const String &rhs);
    	String(char letter, int repeat);
    	~String();
    	void setName(const char* aname);
    	String& operator= (const String &rhs);
    	String& operator= (const char *st);
    	String& operator= (const char st);
    	String& operator+=(const String & str);
    	String operator+() const;
    	char& operator[](int i);
    	char& operator[](int i) const;
    	String& operator++();
    	String& operator--();
    	String operator++(int x);
    	String operator--(int x);
    	int getLength()const;
    	String substr(int start, int length);
    	void print();
    	
        class IndexOutOfBoundsException : public std::out_of_range
        {
        public:
    		IndexOutOfBoundsException() : std::out_of_range("IndexOutOfBoundsException") { }
    	};
    
    
    
    private:
    	int stringlength;
    	int size;
    	char * name;
    	char *buf;
    
    };
    
    #endif 
    
    // string.cpp
    #define _CRT_SECURE_NO_DEPRECATE 1	
    #include <iostream>
    #include <assert.h>
    #include "string.h"
    
    
    using namespace std;
    
    String::String()
    {
    	name = NULL;
    	stringlength = 0;
    	size = stringlength + 1;
    	buf = new char[size];
    	memset(buf, 0, size);
    	assert(buf != 0);
    	buf[0] = '\0';
    }
    
    String::String(const char *str)
    { 
    	name = NULL;
    	assert( str != 0);
    	stringlength = strlen(str);
    	size = stringlength + 1;
    	buf = new char[size];
    	memset(buf, 0, size);
    	strcpy(buf, str);
    }
    
    String::String(char nme)
    {
    	name = NULL;
    	stringlength = 1;
    	size = stringlength + 1;
    	buf = new char[size];
    	memset(buf, 0, size);
    	buf[0] = nme;
    	buf[1] = '\0';
    }
    
    String::String(int sizeofstring)
    {
    	name = NULL;
    	assert(sizeofstring >= 0);
    	stringlength = sizeofstring;
    	size = stringlength + 1;
    	buf = new char[size];
    	memset(buf, 0, size);
    	assert(buf != 0);
    	for(int i =0; i< size; i++)
    		buf[i] = '\0';
    
    }
    
    String::String(char letter, int repeat) : name(0), stringlength(repeat)
    {
    	buf = new char[repeat+1];
        memset( buf, 0, repeat + 1);
    	for(int i= 0; i< repeat; i++)
    		buf[i] = letter;
    }
    
    String::String(const String &rhs)
    {
    	name = NULL;
    	stringlength = rhs.stringlength;
    	size = stringlength + 1;
    	buf = new char[size];
    	memset(buf, 0, size);
    	assert(buf != 0);
    	for (int i=0; i <= stringlength; i++)
    		buf[i] = rhs.buf[i];
    }
    
    String::~String()
    {
    	delete []buf;
    
    }
    
    void String::setName(const char* aname)	
    {
    	name = new char[strlen(aname + 1)];		
    	strcpy(name, aname);					
    }
    
    String& String::operator =(const String &rhs)
    {
    	if(this != &rhs)
    	{
    		delete []buf;
    		stringlength = rhs.stringlength;
    		buf = new char[stringlength + 1];
    		memset(buf, 0, stringlength + 1);
    		strcpy(buf, rhs.buf);
    	}
    	return *this;
    }
    
    String& String::operator =(const char *st)
    {
    	String temp(st);
    	return operator =(temp);
    }
    
    String& String::operator =(char st)
    {
    	stringlength = 1;
    	size = stringlength + 1;
    	buf = new char[size];
    	memset(buf, 0 , size);
    	buf[0] = st;
    	buf[1] = '\0';
    	return *this;
    }
    
    char& String::operator [](int i) const 
    {
    	if(i >= 0 && i < stringlength)
    		throw IndexOutOfBoundsException();
    	return buf[i];
    }
    
    char& String::operator [](int i)
    {
    	if(i >= 0 && i < stringlength)
    		throw IndexOutOfBoundsException();
    	return buf[i];
    }
    
    String& String::operator +=(const String & str)
    {
    	int newsize = getLength() + str.getLength();
    	size = newsize + 1;
    	char *temp = new char[size];
    	memset(temp, 0, size);
    	strcpy(temp, buf);
    	strcat(temp, str.buf);
    	delete []buf;
    	buf = temp;
    	stringlength = newsize;
    	return *this;
    }
    
    int String::getLength()const
    {
    	return stringlength;
    }
    
    
    String operator +(const String& lhs, const String& rhs)
    {
    	String result(lhs);
    	result += rhs;
    	return result;
    }
    
    String operator +(char str, const String& rhs)
    {
    	String result(str);
    	result += rhs;
    	return result;
    }
    
    String operator +(const String& rhs, char str)
    {
    	String result(rhs);
    	result += str;
    	return result;
    }
    
    String operator +(const char* str, const String& rhs)
    {
    	String result(str);
    	result += rhs;
    	return result;
    }
    
    String operator +(const String& rhs, const char* str)
    {
    	String result(rhs);
    	result += str;
    	return result;
    }
    
    
    
    String String::substr(int start, int length)
    {
    	if(start >= 0 && start < stringlength)
    		cout<< "Start of substring not in string bounds" << endl;
    	if(length >= 0)
    		cout<< "Error: length of substring is negative" << endl;
    	if((start + length) > stringlength)
    		length = stringlength - start;
    	char* stringArray = new char[length + 1];
    	memset(stringArray, 0, length +1);
    	int i;
    	for(i = start; i < (start + length) ; i++)
    		stringArray[i-start] = (*this)[i];
    	stringArray[i - start] = '\0';
    	String temp(stringArray);
    	delete []stringArray;
    	return temp;
    }
    
    
    
    int operator==(const String& lhs, const String& rhs)
    {
    	return strcmp(lhs.buf, rhs.buf)==0;
    }
    
    int operator!= (const String& lhs, const String& rhs)
    {
    	return !(lhs.buf == rhs.buf);
    }
    
    int operator< (const String& lhs, const String& rhs)
    {
    	return strcmp(lhs.buf, rhs.buf) <0;
    }
    
    int operator<= (const String& lhs, const String&rhs)
    {
    	return strcmp(lhs.buf, rhs.buf) <=0;
    }
    
    int operator> (const String& lhs, const String& rhs)
    {
    	return strcmp(lhs.buf, rhs.buf) >0;
    }
    
    int operator>= (const String& lhs, const String& rhs)
    {
    	return strcmp(lhs.buf, rhs.buf) >=0;
    }
    
    ostream& operator<< (ostream& output, const String& stringoutput)
    {
    	output<< stringoutput.buf;
    	return output;
    }
    
    
    String& String::operator ++()
    {
    	for(int i = 0; i<stringlength; i++)
    		++buf[i];
    	return *this;
    
    }
    
    String String::operator ++(int x)
    {
    	++buf[x];
    	return *this;
    
    }
    
    String& String::operator --()
    {
    	for(int i = 0; i<stringlength; i++)
    		--buf[i];
    	return *this;
    }
    
    String String::operator --(int x)
    {
    	--buf[x];
    	return *this;
    }
    
    void String::print()
    {
    	for(int i= 0; i<stringlength; i++)
    		printf("&#37;c", buf[i]);
    }

  15. #75
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> String::String(char letter, int repeat) : name(0), stringlength(repeat)
    That constructor isn't quite right, but from the looks of it you added it recently and with a different style than your other ones.

    The other constructors have solved the initialization problem I mentioned before, except now one of your operator= does the same bad thing of not setting all values to valid states.

    Look at how your operator+= sets stringlength at the end of the function. It's not quite right.

    Your operator=(char) has a memory leak. Remember that you need to clean up existing memory inside operator=. Also check your setName function for the same problem.

    I assume you haven't used your operator[] functions yet. You'll see the problem when you do.


    Do you have test code? You should write a small test app that tests one function at a time. Start with a string, run one of the functions, and check the values inside the string to make sure they are accurate. do this for every function separately, and then they should work better when you combine them.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  2. String issues
    By The_professor in forum C++ Programming
    Replies: 7
    Last Post: 06-12-2007, 09:11 AM
  3. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  4. class object manipulation
    By guda in forum C++ Programming
    Replies: 2
    Last Post: 10-09-2004, 10:43 AM
  5. Headers that use each other
    By nickname_changed in forum C++ Programming
    Replies: 7
    Last Post: 10-03-2003, 04:25 AM