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;
}
Your
operator +
is writing past the allocated memory (buffer overflow). You can easily change it to the very simple: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 usestrlen()
,strcpy()
andstrcat()
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: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 usememcpy()
in the constructors instead of thefor (int i = 0; i < size; i++)
loops. Orstrcpy()
and make the string null-terminated (but even thenmemcpy()
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 invalue
).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 stringvalue
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 ofst4
(and any other string assigned with=
). Note that implementing theoperator =
correctly is also tricky - beware of the self-assignment scenario.You error most likely should be on following code:
calls:
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/
There are other issues with your code, most dealing with your comparison operators.
Your
operator <
andoperator==
forMyString
are incorrect. To compare c-style strings, you usestrcmp
, 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 <
andoperator ==
, 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:
Note that the operators use the
<
and==
to implement the other operators.The third issue is that you're missing an assignment operator
Without this function, you cannot assign
MyString
objects to each other without corrupting memory.