Istream operator overloading '>>' cause infinite loop - c++

My college teacher assigned a homework about simulating string, and here's one selection of my code:
// MyString.h
#include <iostream>
#include <cstdio>
#include <string.h>
using std::ostream;
using std::istream;
class MyString{
protected:
char *_data; // data index
int _len; // index size
public:
/////////////////////////////////////////////////////////
char* data()const{
return _data;
}
/////////////////////////////////////////////////////////
MyString& operator=(const char* &rhs){
_data = const_cast<char*>(rhs);
_len = strlen(_data)
}
MyString& operator=(const MyString& rhs){
(*this) = rhs._data;
}
/////////////////////////////////////////////////////////
friend ostream &operator<<( ostream&, const MyString & );
friend istream &operator>>( istream&, MyString & );
};
ostream& operator <<(ostream& os, const MyString& str){
os << str.data();
return os;
}
istream& operator >>(istream& is, MyString& str){
char buffer[0xff];
is.getline(buffer, 0xff);
str = buffer;
return is;
}
I totally have no idea why operator = causes infinite loop here...please help...thanks in advance
Edit:
There goes my buggy code. I have edited where cause the causes infinite loop issue but the rest of them maybe still bugged, I'll try to fix them soon, thank you all!
MyString.h
#include <iostream>
#include <cstdio>
#include <string.h>
using std::ostream;
using std::istream;
class MyString{
protected:
char *_data; // data index
int _len; // index length
static int _total_MyString; // number of instance created
public:
/////////////////////////////////////////////////////////
// basic initialization
MyString(){
_data = NULL;
_len = 0;
_total_MyString++;
}
// init with defined string
MyString(const char *s):MyString(){
(*this)= s;
}
// init with same class data
MyString(const MyString & s):MyString(s._data){}
// finalizer
~MyString(){
_total_MyString--;
delete _data;
}
/////////////////////////////////////////////////////////
static int total_MyString(){
return _total_MyString;
}
/////////////////////////////////////////////////////////
char* data()const{
return _data;
}
/////////////////////////////////////////////////////////
MyString& operator=(const char* &rhs){
char* temp = const_cast<char*>(rhs);
_len = strlen(temp);
_data = new char [_len + 1];
strcpy(_data, rhs);
return (*this);
}
MyString& operator=(const MyString& rhs){
const char* temp = rhs._data;
return (*this = temp);
}
/////////////////////////////////////////////////////////
MyString& operator+=(const char* &rhs){
_len += strlen(rhs);
strcat(_data, rhs);
return *this;
}
MyString& operator+=(const MyString& rhs){
const char* temp = rhs._data;
(*this) += temp;
return *this;
}
/////////////////////////////////////////////////////////
inline char & operator[](const int pos){
return _data[pos];
}
/////////////////////////////////////////////////////////
unsigned length() const{
return _len;
}
/////////////////////////////////////////////////////////
friend ostream &operator<<( ostream&, const MyString & );
friend istream &operator>>( istream&, MyString & );
/////////////////////////////////////////////////////////
bool operator==(const MyString& str){
return !strcmp(_data, str._data);
}
friend bool operator!=(const MyString& str, const MyString& str2){
return strcmp(str._data, str2._data) != 0;
}
};
ostream& operator <<(ostream& os, const MyString& str){
os << str.data();
return os;
}
istream& operator >>(istream& is, MyString& str){
char buffer[0xff];
is.getline(buffer, 0xff);
const char* temp = &buffer[0];
str = temp;
return is;
}
MyString.cpp
#include "MyString.h"
using namespace std ;
int MyString::_total_MyString = 0;
int main()
{
MyString Dstr1("String"), Dstr2("Test String 2"), Dstr3(Dstr1);
cout << "Dstr1 is: " << Dstr1 << endl;
cout << "Dstr2 is: " << Dstr2 << endl;
cout << "Dstr3 is: " << Dstr3 << endl;
cout << "Total MyString_Derived is: " << MyString_Derived::total_MyString() << endl;
/////////////////////////////////////////////////////////
cout << "Give one word "<< endl;
cin >> Dstr1;
cout << "Dstr1 is: " << Dstr1 << endl;
/////////////////////////////////////////////////////////
Dstr2 = Dstr1;
cout << "Dstr2 is: " << Dstr2 << endl;
return 0;
/////////////////////////////////////////////////////////
Dstr3 += Dstr1;
cout << "Dstr3 is: " << Dstr3 << endl;
/////////////////////////////////////////////////////////
cout << "Dstr3 is: ";
for(int i = 0; i<Dstr3.length(); i++)
cout << Dstr3[i];
cout << endl;
for(int i = 0; i<Dstr3.length(); i++)
Dstr3[i] = 'a' + i;
cout << "Dstr3 is: " << Dstr3 << endl;
/////////////////////////////////////////////////////////
cout << "Dstr1 is: " << Dstr1 << endl;
cout << "Dstr2 is: " << Dstr2 << endl;
cout << "Dstr3 is: " << Dstr3 << endl;
cout << "Compare Dstr1 == Dstr2 is: " << (Dstr1 == Dstr2) << endl;
cout << "Compare Dstr1 == Dstr3 is: " << (Dstr1 == Dstr3) << endl;
cout << "Compare Dstr1 != Dstr2 is: " << (Dstr1 != Dstr2) << endl;
cout << "Compare Dstr1 != Dstr3 is: " << (Dstr1 != Dstr3) << endl;
}

Consider the operator>>
istream& operator >>(istream& is, MyString& str){
char buffer[0xff];
is.getline(buffer, 0xff);
const char* temp = &buffer[0];
str = temp;
return is;
}
buffer is a local variable. you create a pointer to this local array and assing it to str. That calls
MyString& operator=(const char* &rhs){
_data = const_cast<char*>(rhs);
_len = strlen(_data);
return (*this);
}
Which is interesting: as a parameter you give the reference to a pointer, which is const, and you then strip the const-ness from it and assign it to _data.
Now char* _data is pointing to the local array buffer. What happens at the end of the function, when the local array is destroyed? The pointer becomes invalid.
You need to implement a deep copy.

Related

Overloading + operator in String class

I have to implement a string class with operators [], +, +=, <<, >>, ==, !=, <, <=, >, >= but I cannot use the string object or include the library for c++. Here is my code so far:
# define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstring>
#include<fstream>
using namespace std;
class MyString {
public:
MyString();
MyString(const char* chars);
int length() const;
char * getValue()const;
~MyString();
//copy constructor
MyString(const MyString&);
MyString& operator =(const MyString& s);
char& operator[](int i);
MyString& operator+=(const MyString& s);
friend ostream& operator<<(ostream&os, const MyString&s);
friend istream& operator >> (istream&is, MyString&s);
friend bool operator ==(const MyString& s1, const MyString& s2);
friend bool operator <(const MyString& s1, const MyString& s2);
private:
char* value;
int size;
};
MyString operator+(const MyString s1, const MyString& s2);
bool operator !=(const MyString& s1, const MyString& s2);
bool operator >=(const MyString& s1, const MyString& s2);
bool operator <=(const MyString& s1, const MyString& s2);
bool operator > (const MyString& s1, const MyString& s2);
//no arguments constructor
MyString::MyString() {
value = 0;
size = 0;
}
//constructor
MyString::MyString(const char* chars) {
size = strlen(chars);
value = new char[size + 1];
strcpy(value, chars);
}
int MyString::length()const {
return size;
}
char* MyString::getValue()const {
return value;
}
MyString::~MyString() {
delete[] value;
}
//copy constructor
MyString::MyString(const MyString& s) {
size = s.size;
value = new char[size + 1];
strcpy(value, s.value);
}
MyString& MyString::operator=(const MyString&s) {
if (s.value == 0) {
delete[] value;
value = 0;
size = 0;
return *this;
}
if (this != &s) {
delete[] value;
value = new char[s.size + 1];
strcpy(value, s.value);
size = s.size;
}
return *this;
}
char& MyString::operator[](int i) {
if (i < 0 || i >= size) {
cout << "Please enter correct value of index" << endl;
exit(0);
}
else {
return value[i];
}
return value[i];
}
MyString& MyString::operator+=(const MyString& s) {
char** temp = &value;
*temp = new char[size];
strcpy(value,*temp);
strcat(value, s.getValue());
if (size != 0) {
delete[] temp;
}
size = strlen(value);
return *this;
}
ostream& operator<<(ostream&out, const MyString&s) {
out << s.value;
return out;
}
istream& operator >> (istream&in, MyString&s) {
char*ptr = new char[100];
in >> ptr;
s = MyString(ptr);
delete ptr;
return in;
}
MyString operator+(const MyString s1, const MyString& s2) {
MyString answer;
answer += s1;
answer+= s2;
return answer;
}
bool operator ==(const MyString&s1, const MyString& s2) {
return(strcmp(s1.value, s2.value) == 0);
}
bool operator<(const MyString& s1, const MyString& s2) {
return (strcmp(s1.value, s2.value) < 0);
}
bool operator !=(const MyString& s1, const MyString& s2) {
return !(s1 == s2);
}
bool operator>(const MyString& s1, const MyString& s2) {
return !(s1 == s2) && !(s1 < s2);
}
bool operator<=(const MyString& s1, const MyString& s2) {
return s1 < s2 || s1 == s2;
}
bool operator >=(const MyString & s1, const MyString& s2) {
return !(s1 < s2);
}
void test_copy_and_destructor(MyString S) {
cout << "test: copy constructor and destructor calls: " << endl;
MyString temp = S;
cout << "temp inside function test_copy_and_destructor: " << temp << endl;
}
int main() {
MyString st1("abc abc");
MyString st2("9fgth");
cout << "Copy constructor , << operator" << endl;
MyString st3(st1);
cout << "st3: " << st3 << endl;
test_copy_and_destructor(st2);
MyString st4;
cout << "operator + " << endl;
st4 = st3 + st2;
cout << "st4: " << st4 << endl;
cout << "st1 + st2: " << (st1 + st2) << endl;
cout << "operators [ ] " << endl;
for (int i = 0; i < st2.length(); i++)
cout << st2[i] << " ";
cout << endl;
cout << "operators += , ==, != " << endl;
st2 += st1;
if (st3 == st1)
cout << "st3 and st1 are identical " << endl;
else cout << "st3 and st1 are not identical " << endl;
if (st2 != st1)
cout << "st2 and st1 are not identical " << endl;
else cout << "st2 and st1 are identical " << endl;
cout << "operators < , <=, >, >= " << endl;
if (st2 < st1)
cout << "st2 < st1 " << endl;
else cout << "st2 is not less than st1 " << endl;
if (st1 <= st2)
cout << "st1 <= st2 " << endl;
else cout << "st1 is not less than or equal to st2 " << endl;
if (st1 > st2)
cout << "st1 > st2 " << endl;
else cout << "not (st1 > st2) " << endl;
if (st1 >= st2)
cout << "st1 >= st2 " << endl;
else cout << "not (st1 >= st2) " << endl;
cout << "operator >> " << endl;
//Open the data file
ifstream input("A9_input.txt");
if (input.fail()) {
cout << "unable to open input file A9_input.txt, Exiting..... ";
return 0;
}
MyString temp1;
MyString temp2("aaa");
input >> temp1;
input >> temp2;
cout << "first element of input file: " << temp1 << endl;
cout << "second element of input file: " << temp2 << endl;
input.close();
cout << "MyString says farewell....." << endl;
return 0;
}
After reaching operator + my code reaches break point and crashes. I could tell something is wrong with my += operator code as + is using += code. Can someone help me figure out what is wrong with my += code?
The problem is that you are using strcpy() and strcat() to populate the old allocation, which is not large enough. Therefore, the strcat() invocation attempts to write past the end of this allocation and the result is undefined behavior, which is manifesting as a crash on your system.
char* temp = value;
temp = new char[strlen(value) + s.length() +1];
strcpy(value, temp); // <-- should be copying the other way
strcat(value, s.getValue()); // <-- should be copying into temp, not value
//if (size != 0) {
// delete[]temp;
//}
size = strlen(value);
return *this;
Rewritten to solve this problem, as well as release the original string, and check for value == nullptr:
char *oldString = value == nullptr ? "" : value;
int newSize = strlen(oldString) + s.length();
char *newString = new char[newSize + 1];
strcpy(newString, oldString);
strcat(newString, s.getValue());
delete [] value;
value = newString;
size = newSize;
return *this;
your problem is that you are trying to change what you pointer points to be using a pointer and not pointer to pointer.
when you are using the new operator your pointer simply gets new adress at the heap and than the assignment you did before(char * temp = value) is irelvent.
beacuse temp gets the adress pointed by value and not value adress, than any modification on temp adress will not effect value.
what you really wanna do is :
char * temp = new char[size]
//modify temp(add the strings)
//change value to hold the modified string
value = temp;
you can also do that :
char ** temp = &value;//now temp holds value's address.
*temp = new char[size];
//modify temp will modify value, but you need to derefrence before each use.
update
you are trying to copy a larger string temp into value which casues overflow (its a good practise to use strcpy_s/strcat_s beacuse they cannot copy more than the length you give them, that should be the size of dest).
link to strcpy/strcpy_s doc :
http://en.cppreference.com/w/c/string/byte/strcpy
http://en.cppreference.com/w/c/string/byte/strcat
what you should do is :
char * temp = new char[size];
//strcpy_s(dest, length of dest, src)
strcpy_s(temp , sizeof temp, value);//copy value to temp
strcat_s(temp, sizeof temp, s.getValue());
if(value != nullptr)
delete [] value;
value = temp;

Exception thrown at 0x0F640E09 (ucrtbased.dll) in ConsoleApplication5.exe: 0xC0000005: Access violation writing location 0x014C3000?

I just compiled this code, and it showed me this error:
Exception thrown at 0x0F640E09 (ucrtbased.dll) in ConsoleApplication5.exe: 0xC0000005: Access violation writing location 0x014C3000. I literally have no idea what this error means as I've just been using C++ for a couple months, and I've also tried looking on any other websites to look for help, but I didn't find any.
For this code, I'm only allowed to use the c-string functions and the <cstring> library. I cannot use the string object or include the library. I can also use helper methods/functions.
#include <iostream>
#include <cstring>
#include <fstream>
using namespace std;
class MyString {
public:
//default constructor
MyString();
MyString(char* chars);
//copy constructor
MyString(const MyString &);
int length() const;
//destructor
~MyString();
//operator overloads
char& operator[](int index);
friend MyString operator+(const MyString& newWord, const MyString& newWord2);
MyString& operator+=(const MyString& newWord);
friend ostream& operator<<(ostream& newWord, const MyString& newWord2);
friend istream& operator >> (istream& newWord, MyString& newWord2);
friend bool operator==(const MyString& newWord, const MyString& newWord2);
friend bool operator!=(const MyString& newWord, const MyString& newWord2);
friend bool operator<(const MyString& newWord, const MyString& newWord2);
friend bool operator<=(const MyString& newWord, const MyString& newWord2);
friend bool operator>(const MyString& newWord, const MyString& newWord2);
friend bool operator>=(const MyString& newWord, const MyString& newWord2);
private:
char* value;
int size;
};
//default constructor
MyString::MyString() {
value = 0;
size = 0;
}
//copy constructor
MyString::MyString(const MyString& newWord) {
//perform a deep copy to copy each of the value to a new memory
size = newWord.size;
value = new char[size];
for (int ii = 0; ii < size; ii++) {
value[ii] = newWord.value[ii];
}
}
//constructor with an argument
MyString::MyString(char* chars) {
size = strlen(chars);
value = new char[size];
for (int i = 0; i < size; i++) {
value[i] = chars[i];
}
}
//find length
int MyString::length() const {
return size;
}
//find the value of each index
char& MyString::operator[](int index) {
return value[index];
}
//operator + (concatenate)
MyString operator+(const MyString& newWord, const MyString& newWord2) {
MyString concatenated;
concatenated = strcat(newWord.value, newWord.value);
return concatenated;
}
//operator += (append)
MyString& MyString::operator+=(const MyString& newWord) {
char * newMemory = value;
value = new char[strlen(value) + newWord.length() + 1];
strcpy(value, newMemory);
strcat(value, newWord.value);
if (size != 0)
{
delete[] newMemory;
}
size = strlen(value);
return *this;
}
//ostream operator
ostream& operator<<(ostream& newWord, const MyString& newWord2) {
newWord << newWord2.value;
return newWord;
}
//istream operator
istream& operator >> (istream& newWord, MyString& newWord2) {
const int MAX = 100;
char* ptr = new char[MAX];
newWord >> ptr;
newWord2 = MyString(ptr);
delete ptr;
return newWord;
}
//all boolean operators
bool operator==(const MyString& newWord, const MyString& newWord2) {
if (newWord.value == newWord2.value) {
return true;
}
else {
return false;
}
}
bool operator!=(const MyString& newWord, const MyString& newWord2) {
if (newWord.value != newWord2.value) {
return true;
}
else {
return false;
}
}
bool operator<(const MyString& newWord, const MyString& newWord2) {
if (newWord.value < newWord2.value) {
return true;
}
else {
return false;
}
}
bool operator<=(const MyString& newWord, const MyString& newWord2) {
if (newWord.value <= newWord2.value) {
return true;
}
else {
return false;
}
}
bool operator>(const MyString& newWord, const MyString& newWord2) {
if (newWord.value > newWord2.value) {
return true;
}
else {
return false;
}
}
bool operator>=(const MyString& newWord, const MyString& newWord2) {
if (newWord.value >= newWord2.value) {
return true;
}
else {
return false;
}
}
//destructor to release memory
MyString::~MyString() {
delete[] value;
}
void test_copy_and_destructor(MyString S) {
cout << "test: copy constructor and destructor calls: " << endl;
MyString temp = S;
cout << "temp inside function test_copy_and_destructor: " << temp << endl;
}
int main() {
MyString st1("abc abc");
MyString st2("9fgth");
cout << "Copy constructor , << operator" << endl;
MyString st3(st1);
cout << "st3: " << st3 << endl;
test_copy_and_destructor(st2);
MyString st4;
cout << "operator + " << endl;
st4 = st3 + st2;
cout << "st4: " << st4 << endl;
cout << "st1 + st2: " << (st1 + st2) << endl;
cout << "operators [ ] " << endl;
for (int i = 0; i < st2.length(); i++)
cout << st2[i] << " ";
cout << endl;
cout << "operators += , ==, != " << endl;
st2 += st1;
if (st3 == st1)
cout << "st3 and st1 are identical " << endl;
else cout << "st3 and st1 are not identical " << endl;
if (st2 != st1)
cout << "st2 and st1 are not identical " << endl;
else cout << "st2 and st1 are identical " << endl;
cout << "operators < , <=, >, >= " << endl;
if (st2 < st1)
cout << "st2 < st1 " << endl;
else cout << "st2 is not less than st1 " << endl;
if (st1 <= st2)
cout << "st1 <= st2 " << endl;
else cout << "st1 is not less than or equal to st2 " << endl;
if (st1 > st2)
cout << "st1 > st2 " << endl;
else cout << "not (st1 > st2) " << endl;
if (st1 >= st2)
cout << "st1 >= st2 " << endl;
else cout << "not (st1 >= st2) " << endl;
cout << "operator >> " << endl;
//Open the data file
ifstream input("A9_input.txt");
if (input.fail()) {
cout << "unable to open input file A9_input.txt, Exiting..... ";
system("pause");
return 0;
}
MyString temp1;
MyString temp2("aaa");
input >> temp1;
input >> temp2;
cout << "first element of input file: " << temp1 << endl;
cout << "second element of input file: " << temp2 << endl;
input.close();
cout << "MyString says farewell....." << endl;
system("pause");
return 0;
}
You error most likely should be on following code:
st4 = st3 + st2; # note that you initialize st4 with type MyString but inside operator+ you assign a char[] to MyString. Just letting you know since you dont have a operator= overloaded function
calls:
MyString operator+(const MyString& newWord, const MyString& newWord2) {
MyString concatenated;
concatenated = strcat(newWord.value, newWord.value); # you have an mistake here, second parameter should be newWord2.value
return concatenated;
}
You are making an assumption that your newWord.value holds enough space to hold newWord.value and newWord2.value. but it is not you inisialized it on your constructor to be newWord.value so you are basically writng in to a region that violate memory access. What you want to do is make newWord big enough to hold both strings.
reference to strcat : http://www.cplusplus.com/reference/cstring/strcat/
Your operator + is writing past the allocated memory (buffer overflow). You can easily change it to the very simple:
MyString operator +(const MyString& newWord, const MyString& newWord2) {
MyString concatenated;
return concatenated += newWord2;
}
then it even doesn't need to be a friend of the class.
Also the operator += is wrong, because your strings are not created NULL terminated initially, so in the fact you shouldn't use strlen(), strcpy() and strcat() at all, because you are then concatenating arbitrary memory together (reading past allocated memory can also segfault). So you should make your mind whether you want the strings NULL terminated (and used as such) or not.
The operator += is also not defined very effectively anyway, more clean and effective could be for example:
MyString& MyString::operator+=(const MyString& newWord) {
size_t newSize = size + newWord.size;
char * newValue = new char[newSize /* + 1 */]; // not null terminated, but cannot be printed easily then
// or make the string initially null terminated and then allocate +1 and null terminate then
memcpy(newValue, value, size);
memcpy(newValue + size, newWord.value, newWord.size /* + 1 */);
delete[] value;
value = newValue;
size = newSize;
return *this;
}
See? No use of strlen() which traverses the strings (not null terminated in your case), because you know the size of the string anyway. You can also use memcpy() in the constructors instead of the for (int i = 0; i < size; i++) loops. Or strcpy() and make the string null-terminated (but even then memcpy() can be used as it is faster - does not test for the '\0' on every character copied).
The operators ==, != do not seem very correct either, as only the pointers are compared (so the string will only ever be equal to itself, but not to other string with the same characters stored in value).
Furthermore, as the initial strings are not null terminated, the operator << will not work correctly either (will print out arbitrary memory past the string). In general, I would recommend to make the string value always null terminated to avoid some of the issues.
And finally, you definitely need to define operator =, because for now you are using the default one which does a shallow copy, so with this code you will have double-free at destruction of st4 (and any other string assigned with =). Note that implementing the operator = correctly is also tricky - beware of the self-assignment scenario.
There are other issues with your code, most dealing with your comparison operators.
Your operator < and operator== for MyString are incorrect. To compare c-style strings, you use strcmp, not ==. Your comparison operators instead is comparing pointer values, not the data that is being pointed to.
The second issue is that all you need to do is fully implement operator < and operator ==, as all of the other comparison operators can be implemented in terms of these functions.
Putting this all together, the implementation of your class should look something like this:
#include <cstring>
//...
class MyString {
public:
//...
friend bool operator==(const MyString& newWord, const MyString& newWord2);
friend bool operator!=(const MyString& newWord, const MyString& newWord2);
friend bool operator<(const MyString& newWord, const MyString& newWord2);
friend bool operator<=(const MyString& newWord, const MyString& newWord2);
friend bool operator>(const MyString& newWord, const MyString& newWord2);
friend bool operator>=(const MyString& newWord, const MyString& newWord2);
private:
char* value;
int size;
};
bool operator==(const MyString& newWord, const MyString& newWord2)
{ return strcmp(newWord.value, newWord2.value) == 0; }
bool operator<(const MyString& newWord, const MyString& newWord2)
{ return strcmp(newWord.value, newWord2.value) == -1; }
bool operator!=(const MyString& newWord, const MyString& newWord2)
{ return !(newWord == newWord2); }
bool operator<=(const MyString& newWord, const MyString& newWord2)
{ return !(newWord2 < newWord); }
bool operator> (const MyString& newWord, const MyString& newWord2)
{ return newWord2 < newWord; }
bool operator>=(const MyString& newWord, const MyString& newWord2)
{ return !(newWord < newWord2); }
Note that the operators use the < and == to implement the other operators.
The third issue is that you're missing an assignment operator
MyString& operator=(const MyString&)
Without this function, you cannot assign MyString objects to each other without corrupting memory.

Assignment operator overloading - deleting heap memory causes crash

I am writing to write a string class and while doing assignment operator overloading I am observing crash at the part where we do deletion of previously allocated memory. I tried to trace through code but couldn't figure it out. Any pointers would help
str& str::operator=(const str &Rhs)
{
if (this != &Rhs)
{
cout << " attempt of self allocation - " << endl;
**delete[] this->_element;** // crashes here
this->_capacity = Rhs._capacity;
this->_display = Rhs._display;
this->_size = Rhs._size;
if (Rhs._size > 0)
{
this->_element = new char(this->_size);
if (this->_element == NULL)
{
cout << " mem allocation failed " << endl;
}
}
for (int counter = 0; counter <= this->_size; counter++)
{
this->_element[counter] = Rhs._element[counter];
}
}
return *this;
}
/*copy constructor */
str::str(const str& Rhs)
{
// copy constructor called
this->_capacity = Rhs._capacity;
this->_display = Rhs._display;
this->_size = Rhs._size;
if (Rhs._size > 0)
{
this->_element = new char(_size);
if (this->_element == NULL)
{
cout << " mem allocation failed " << endl;
}
for (int counter = 0; counter <= this->_size; counter++)
{
this->_element[counter] = Rhs._element[counter];
}
}
}
/* constructor */
str::str(const char *Y)
{
cout << "constructor called !!! -- " << endl;
size_t len = this->stringlen(Y);
this->_element = new char(len + 1);
for (int counter = 0; counter < len; counter++)
{
this->_element[counter] = Y[counter];
}
this->_element[len] = '\0';
this->_size = len + 1;
cout << "string in constructor is -- " << this->_element << endl;
}
From .h file
class str
{
public:
/*Default Constructor*/
explicit str();
/*Constructor with single char Argument*/
explicit str(char x);
/*Constructor with char array Argument*/
explicit str(const char* Y);
/* Creating new element with copy constructor */
str(const str& Rhs);
/* Overloading of Assignment operator */
str& operator=(const str& Rhs);
friend int string_compare(const str& Lhs, const str& Rhs);
int reverse();
size_t stringlen(const char* Y);
str& operator+(str& Rhs);
bool operator==(const str& Rhs);
bool operator!=(const str& Rhs);
friend ostream& operator<<(ostream &out, str& Lhs);
private:
char* _element;
int _capacity;
bool _display;
int _size; //largest accessed + 1
};
Main Routine -
void test1() {
const char *j = "abc";
cout << "length of j = " << strlen(j) << endl;
str s1('U');
str s2("hello");
cout << s2 << endl;
s2.reverse();
cout << s2 << endl;
str s3(s2);
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
**s2 = s1;** // crashes
cout << s2 << endl;
cout << s1 << endl;
}
There are several problems with your code.
The biggest one is: if you want to allocate an array you need to use new char[_size]. new char(_size) allocates one char with its value set to _size.
Second, once you fix that problem, you write past the end of your allocated array - judging by the comment in your header you need to allocate char[_size + 1].
Third, in your copy constructor you never initialize the _element array and in your assignment operator you never clear up the _element value. This will eventually lead to crash when you copy or assign an empty str and then try to assign to it (or at destruction time as I assume that the destructor also calls delete).

Expression: _BLOCK_TYPE_IS_VALID problems with deleting pointers

I've been working on this code for a while trying to test out my Company class with a test bed main. I get all the results I want, however upon finishing the main function the program crashes giving
this message:
(I apologize but I'm new here and I can't directly post the image yet.)
I've been dealing with this error for probably about 4-5 hours spanning over a couple of days and everything I find doesn't seem to work. I feel like understand pointers as a whole better from the looking around I've done but I still can't seem to find what the problem is.
//COMPANY.H
#ifndef _COMPANY_H
#define _COMPANY_H
#include <stddef.h>
#include <fstream>
#include <iomanip>
enum { PHONE_LEN = 10 };
enum { MAX_NAME_LEN = 30 };
#define _TESTING_COMP
#ifdef _TESTING_COMP
#include <iostream>
using namespace std;
#endif
class Company
{
public:
Company();
~Company();
Company &operator =(Company const & c);
bool operator==(const Company & c)const {return (*name == *c.name);}
bool operator!=(const Company & c)const {return (*name != *c.name);}
bool operator<(const Company & c)const {return (*name < *c.name);}
friend istream & operator>>(istream & in, Company & c);
friend ostream & operator<<(ostream & out, const Company & c);
private:
char *name; // allocate memory (use new) - zero-terminated
char phone[PHONE_LEN]; // NOT zero-terminated (be careful!)
};
#endif
This is my header file with the function and data declarations.
//COMPANY.CPP
#include "Company.h"
Company::Company()
{
name = new char [MAX_NAME_LEN];
}
Company::~Company()
{
delete [] name;
}
Company &Company::operator =(Company const & c)
{
for (int i = 0; i < MAX_NAME_LEN; i++)
*(name + i) = *(c.name + i);
for (int i = 0; i < PHONE_LEN; i++)
phone[i] = c.phone[i];
return *this;
}
istream & operator>>(istream & in, Company & c)
{
in >> c.name;
for (int i = 0; i < PHONE_LEN; i++)
in >> c.phone[i];
return in;
}
ostream & operator<<(ostream & out, const Company & c)
{
//because value is a pointer the * is needed to input a value
out << c.name << setiosflags(ios::left) << setw(MAX_NAME_LEN) << "";
for (int i = 0; i < PHONE_LEN; i++)
out << c.phone[i];
out << endl;
return out;
}
#ifdef _TESTING_COMP
void main ()
{
char end;
Company test1, test2;
cin >> test1;
cout << test1;
cin >> test2;
cout << test2;
cout << "testing comp1 < comp2: expecting (0)" << (test1 < test2) << endl;
cout << "testing comp2 < comp1: expecting (1)" << (test2 < test1) << endl;
cout << "testing comp2 == comp1: expecting (0)" << (test2 == test1) << endl;
cout << "testing comp2 != comp1: expecting (1)" << (test2 != test1) << endl;
cout << "set test1 to = test2" << endl;
test1 = test2;
cout << test1;
cout << test2;
cout << "testing comp1 < comp2: expecting (0)" << (test1 < test2) << endl;
cout << "testing comp2 < comp1: expecting (0)" << (test2 < test1) << endl;
cout << "testing comp2 == comp1: expecting (1)" << (test2 == test1) << endl;
cout << "testing comp2 != comp1: expecting (0)" << (test2 != test1) << endl;
test1.~Company();
test2.~Company();
cin >> end;
}
#endif
and this is the cpp file that holds the extra code and the testbed main.
If you guys could help me out with this user error it would be much obliged. Even if you can't thanks for the time. I'm not entirely sure of what I should be looking for so
these are the data values at the end of the program
I can post more if you guys need it thank you.
So much boilerplate that is unnecessary. By dynamically allocating name there's a whole bunch of housekeeping that you're forced to do for no good reason (and is ultimately the cause of your crash). Also, all of your comparison functions will give you surprising results.
Here's your class refactored as cannonical C++:
#include <string>
class Company
{
public:
const std::string& get_name() const { return name; }
const std::string& get_phone() const { return phone; }
private:
std::string name;
std::string phone;
friend istream & operator>>(istream & in, Company & c);
friend ostream & operator<<(ostream & out, const Company & c);
};
bool operator==(const Company& lhs, const Company& rhs) { return lhs.name == rhs.name; }
bool operator!=(const Company& lhs, const Company& rhs) { return !(lhs == rhs); }
bool operator<(const Company& lhs, const Company& rhs) { return lhs.name < rhs.name; }

C++ operator overload doesnt work

I have a question about operators and how to overload them. There is an example of code and I'm overloading operator<< but it doesn't work. There is class that I use:
class CStudent{ //class for students and their attributes
int m_id;
int m_age;
float m_studyAverage;
public:
CStudent(int initId, int initAge, float initStudyAverage): m_id(initId), m_age(initAge), m_studyAverage(initStudyAverage){}
int changeId(int newId){
m_id = newId;
return m_id;
}
int increaseAge(){
m_age++;
return m_age;
}
float changeStudyAverage(float value){
m_studyAverage += value;
return m_studyAverage;
}
void printDetails(){
cout << m_id << endl;
cout << m_age << endl;
cout << m_studyAverage << endl;
}
friend ostream operator<< (ostream stream, const CStudent student);
};
Overload:
ostream operator<< (ostream stream, const CStudent student){
stream << student.m_id << endl;
stream << student.m_age << endl;
stream << student.m_studyAverage << endl;
return stream;
}
And there is main method:
int main(){
CStudent peter(1564212,20,1.1);
CStudent carl(154624,24,2.6);
cout << "Before the change" << endl;
peter.printDetails();
cout << carl;
peter.increaseAge();
peter.changeStudyAverage(0.3);
carl.changeId(221783);
carl.changeStudyAverage(-1.1);
cout << "After the change" << endl;
peter.printDetails();
cout << carl;
return 0;
}
Where is the problem?
The problem here is you need to learn what references are and the difference between std::ostream and std::ostream& is.
std::ostream& operator<< (std::ostream& stream, const CStudent& student)