crash, delete [ ] this->str - c++

Hello I've got some troubles to delete a member string of my class which is isn't null and which points to the right location since I can display my string "hello world" just before.
I call the function mystringclass::alloc() from another member function afterwards this->str was supposed to get another string content larger.
The process worked fine a first time when I resized the same way "hello" to get "hello world". But now I want to enlarge it again it doesn't. So I'm confused.
Please help me.
void mystringclass::alloc(long newsize) //newsize includes the +1 char
{
cout << "old size was: " << this->size << endl; //displays "12"
if(this->str) cout << this->str << endl; //displays "hello world" all is right till here
if(this->str) delete [] this->str ; //it crashes here
cout << "str deleted\n"; //never show up on screen
this->str = new char[newsize + 1];
this->size = newsize;
this->str[0] = 0;
}
Thanks for your answers, I tried to clear my code to post it here. My bug disappeared but another one came up and having something to do with the rule of three:
int main()
{
stringclass str = "Hello";
stringclass str2 = str;
return 0;
}
I display info all along procedures So the problem is that str2 is already equal to "hello" even before affecting the content of str in my copy constructor. And is empty after the copy. What's wrong? As some may say, I learned c++ in a magicbox. I'm using codeblocks 10.05
Full code :
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
class stringclass
{
protected :
inline bool success() { failbit = false; return true; }
inline bool fail() { failbit = true; return false; }
public :
bool failbit;
char * mystring;
long memsize;
long length;
void alloc(long newsize);
void reset();
void copy(const stringclass & other);
stringclass() {reset(); }
stringclass(const stringclass & other) {copy(other); }
stringclass(const char str[]);
~stringclass() {delete [] mystring;}
inline long get_length() { if(mystring) length = strlen(mystring); return length;}
inline long get_memsize() const { return memsize; }
friend ostream& operator << (ostream& out, stringclass & sc){out << sc.mystring; return out;}
stringclass & operator = (stringclass & other) { copy(other); return *this;}
};
void stringclass::reset()
{
delete [] mystring;
mystring = NULL;
length = 0;
memsize = 0;
}
void stringclass::alloc(long newsize)
{
cout<< "\nalloc(long newsize)... \n" << endl;
cout << "memsize was : " << memsize << endl;
cout << "length was : " << length << endl;
if(mystring) cout << "mystring = " << mystring << endl;
delete [] mystring;
cout << "mystring deleted...\n";
mystring = new char[newsize];
cout << "mystring has been resized\n";
mystring[0] = 0;
memsize = newsize;
length = strlen(mystring);
cout << "memsize is now : " << memsize << endl;
cout << "length is now : " << length << endl;
cout<< "\nend of alloc()... " << endl;
cout << "\n";
}
void stringclass::copy(const stringclass & other)
{
cout << "\n";
cout << "copy(const stringclass & other)...\n" << endl;
cout << "other.mystring = "<< other.mystring << endl;
if(other.mystring == NULL || other.memsize == 0)
{
reset();
return;
}
alloc(other.memsize);
strcpy(mystring, other.mystring);
cout << "mystring = "<< mystring;
length = strlen(mystring);
cout << "length: " << length << endl;
cout<< "\nend of copy()... " << endl;
cout << "\n";
}
stringclass::stringclass(const char str[]) : mystring(NULL), memsize(0), length(0)
{
if(str == NULL) reset();
else
{
alloc(strlen(str) + 1);
strcpy(mystring, str);
length = strlen(mystring);
}
}
int main()
{
stringclass str = "Hello";
stringclass str2 = str;
cout << "\nback to main()...\n";
cout << "str = " << str << "\n";
cout << "str2 = " << str2 << "\n";
cout << endl;
system("PAUSE");
return 0;
}
Result on screen :
alloc(long newsize)...
memsize was : 0
length was : 0
mystring deleted...
mystring has been resized
memsize is now : 6
length is now : 0
end of alloc()...
copy(const stringclass & other)...
other.mystring = Hello
alloc(long newsize)...
memsize was : 3214960
length was : 2293560
mystring = Hello
mystring deleted...
mystring has been resized
memsize is now : 6
length is now : 0
end of alloc()...
mystring = length: 0
end of copy()...
back to main()...
str =
str2 =
Appuyez sur une touche pour continuer...
I've just realized that the following code isn't necessary for you :
protected :
inline bool success() { failbit = false; return true; }
inline bool fail() { failbit = true; return false; }
public :
bool failbit;
So I put off these two functions and this variable, and guess what.. all worked fine, no bug. They are not even used once. I put it back and the problem came back as well. How could you explain that?! I'm already losing my hairs.

The fact that you can "display" a string says absolutely nothing unfortunately. De-allocating the string will still make it printable, most likely until it's overwritten by a new llocation and initialization.
Just try to print the string after you've delete[]d it and see.

Related

Why we have to use const in copy constructor and assignment operator in visual studio 2019 and onwards versions

As you can see that operator+ is returning an object of class type MyString.
The assignment operator is not accepting this object in Visual Studio 2019 and giving an error of E0349 that no operands matches. But, in Visual Studio 2012, it is running fine.
Code:
#include <iostream>
using namespace std;
class MyString {
private:
char* str;
int length;
public:
MyString();
MyString(const MyString&);
bool operator!();
friend ostream& operator<<(ostream&, MyString&);
friend istream& operator>>(istream&, MyString&);
MyString& operator=(const MyString&);
MyString operator+(MyString&);
MyString& operator-(MyString);
MyString& operator ++ ();
MyString& operator -- ();
bool operator<(MyString&);
char& operator[](int);
char* operator()(int, int);
void my_strcpy(char*&, char*);
int my_strlen(char*);
};
MyString::MyString() {
str = new char[1];
str[0] = '\0';
length = 0;
}
MyString::MyString(const MyString& obj) {
int size = my_strlen(obj.str) + 1;
str = new char[size];
cout << "copy constructor called\n";
my_strcpy(str, obj.str);
}
bool MyString::operator!() {
if (str[0] == '\0')
return true;
return false;
}
ostream& operator<<(ostream& output, MyString& obj) {
output << obj.str;
return output;
}
istream& operator>>(istream& input, MyString& obj) {
delete obj.str;
obj.str = new char[50];
input.getline(obj.str, 50);
return input;
}
MyString& MyString::operator=(const MyString& obj) {
if (this != &obj) {
my_strcpy(str, obj.str);
}
return *this;
}
char& MyString::operator[](int index) {
if (index >= 0 && index < my_strlen(str))
return str[index];
else {
clog << "Index is out of range\n", exit(1);
}
}
void MyString::my_strcpy(char*& destination, char* source) {
int len_des = my_strlen(destination);
int len_source = my_strlen(source);
delete[]destination;
destination = new char[len_source + 1];
int index = 0;
while (source[index] != '\0')
destination[index] = source[index++];
destination[index] = '\0';
}
MyString MyString::operator+(MyString& obj) {
MyString newObj;
int size = my_strlen(str) + my_strlen(obj.str) + 1;
newObj.str = new char[size];
char* temp = newObj.str;
int index_str = 0;
while (str[index_str] != '\0')
*newObj.str++ = str[index_str++];
index_str = 0;
while (obj.str[index_str] != '\0')
*newObj.str++ = obj.str[index_str++];
*newObj.str = '\0';
newObj.str = temp;
cout << newObj.str << endl;
return newObj;
}
MyString& MyString::operator ++ () {
int size = my_strlen(str) + 2;
char* new_str = new char[size];
char* temp = new_str;
int index = 0;
while (str[index] != '\0')
*new_str++ = str[index++];
*new_str++ = 'a';
*new_str = '\0';
delete[]str;
str = temp;
return *this;
}
MyString& MyString::operator -- () {
int size = my_strlen(str);
char* new_str = new char[size];
char* temp = new_str;
int index = 0;
while (index < size - 1)
*new_str++ = str[index++];
*new_str = '\0';
delete[]str;
str = temp;
return *this;
}
MyString& MyString::operator-(MyString obj) {
bool find = true;
int obj_str_len = my_strlen(obj.str);
int str_len = my_strlen(str);
int start_ind = 0, end_ind = 0;
if (str_len > obj_str_len) {
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] == obj.str[0]) {
start_ind = i;
find = true;
for (int j = i + 1, k = 1; obj.str[k] != '\0' && find; j++, k++) {
if (str[j] != obj.str[k]) {
find = false;
}
end_ind = j + 1;
}
if (find)
break;
}
}
if (find) {
while (str[end_ind] != '\0') {
str[start_ind++] = str[end_ind++];
}
str[str_len - (end_ind - start_ind)] = '\0';
}
}
return *this;
}
bool MyString::operator<(MyString& obj) {
if (my_strlen(str) < my_strlen(obj.str))
return true;
else if (my_strlen(str) > my_strlen(obj.str))
return false;
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] < obj.str[i])
return true;
else if (str[i] > obj.str[i]) {
return false;
}
}
return false;
}
char* MyString::operator()(int starting_index, int ending_index) {
int new_str_size = ending_index - starting_index + 2;
char* new_str = new char[new_str_size];
char* temp = new_str;
int index = 0;
int str_len = my_strlen(str);
while (starting_index < str_len && index < 10)
*new_str++ = str[starting_index++], index++;
*new_str = '\0';
return temp;
}
int MyString::my_strlen(char* str) {
int size = 0;
while (str[size] != '\0')
size++;
return size;
}
int main() {
MyString str1, str2, str3, str4, str6;
if (!str1)
{
cout << "String 1 is Empty.\n";
cout << "Str 1 = " << str1 << endl << endl << endl;
}
cout << "Enter String 1:\t";
cin >> str1;
cout << "Enter String 2:\t";
cin >> str2;
cout << "\n\n\nUser Entered:\n";
cout << "String 1 = " << str1 << endl;
cout << "String 2 = " << str2 << endl << endl << endl;
cout << "Before str1 = str1; str1 = " << str1 << endl;
str1 = str1;
cout << "After str1 = str1, str1 = " << str1 << endl << endl << endl;
cout << "Before str4 = str3 = str1+str2\n";
cout << "str1 = " << str1 << endl;
cout << "str2 = " << str2 << endl;
cout << "str3 = " << str3 << endl;
cout << "str4 = " << str4 << endl;
str4 = str3 = str1 + str2;
cout << "\n\n\nAfter str4 = str3 = str1+str2\n";
cout << "str1 = " << str1 << endl;
cout << "str2 = " << str2 << endl;
cout << "str3 = " << str3 << endl;
cout << "str4 = " << str4 << endl;
cout << "\n\n\nEnter String 3:\t";
cin >> str3;
cout << "\n\n\nEnter String 4:\t";
cin >> str4;
cout << "\n\n\nstr3 = " << str3 << endl;
cout << "str4 = " << str4 << endl;
if (str3 < str4)
cout << "String 3 is Less than String 4.\n";
else
cout << "String 3 is NOT Less than String 4.\n";
MyString str5 = str1 + str2;;
cout << "\n\n\nStr5:\t" << str5 << endl;
cout << "Str5[7]:\t" << str5[7] << endl;
str5[7] = '$';
cout << "\n\nStr5:\t" << str5 << endl;
cout << "\n\n\nstr5(5, 10):\t" << str5(5, 10) << endl;
cout << "\n\n ++Str3 :\t" << ++str3 << endl;
str5 = str4 - str3;
cout << "\n\n Str4 - Str3 :\t" << str5 << endl;
cout << "\n\n --Str3 :\t" << --str3 << endl;
cout << "\n\n --Str3 :\t" << --str3 << endl;
str5 = str4 - str3;
cout << "\n\n Str4 - str3 :\t" << str5 << endl;
return 0;
}
Problem:
The lines str3 = str1 + str2; and MyString str4 = str1 + str2; will give an error that no operands matches. This error starts from Visual Studio 2019 and onwards versions.
But, when I use const in both copy constructor and assignment operator (such as MyString(const MyString&); MyString& operator=(const MyString&);), both lines (str3 = str1 + str2; MyString str4 = str1 + str2;) looks fine to compiler.
But if I Write str3 = str1; and MyString str4 = str2; now there is no need to write const in the copy constructor and assignment operator.
Why is the compiler showing this behaviour.?
The assignment operator that you have defined (i.e., taking a non-const reference) requires that its argument be (or be convertible to) an lvalue reference because it is non-const.
However, the right-hand side of the assignment operator in the expression, str3 = str1 + str2 is the result of the addition, which is a temporary value and, as such, is a prvalue that cannot be (implicitly) converted to an lvalue.
Adding the const qualifier to the parameter allows that operator to accept rvalue references (because you are explicitly stating that the referred-to value will not be modified).
This is why, generally, copy constructors and copy assignment operators are defined with const &T parameters (though they don't have to be).
For a fuller discussion of the differences between lvalues and rvalues, see here: Exact difference between rvalue and lvalue.
On why/how this "binding of a temporary to an lvalue reference" was allowed in the earlier version(s) of Visual Studio, see: Non-const reference bound to temporary, Visual Studio bug?.

Having difficulty creating operator overload for class module using literal string as argument

I am relatively new to C++. I am hoping to get assistance creating an overload operator that will permit me to use a literal string with a class I am writing. This project is for learning.
I created a custom Date class (and have not worried about the actual logic in the class; I'm just trying to get the interface working and to understand where my roadblock is.
It may not look like it, but I have put in a lot of time on this, so an explanation designed for a beginning c++ progammer would be very helpful to me and anyone who follows in my footsteps.
Basically, I'd like to be able to do this with my class:
Date dt(5,6,92);//create class object
int myint;
myint = dt;//this works
string mystr;
mystr = dt("mm/dd/yy");//this does not compile
Thanks in advance. (A compilable test program shown below)
#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
class Date
{
int mo, da, yr;
public:
Date(int m, int d, int y)
{
cout << "Constructor int m, int d, int y called " << endl;
mo = m; da = d; yr = y;
}
string getdatestr(const char *s = "") {//user sends in format "d2/" "mm/dd/yy" etc
cout << "getdatestr const char *s called mo = " << mo << " da = " << da << "yr = " << yr << endl;
return to_string(mo) + "/" + to_string(da) + "/" + to_string(yr);
}
int getdate(){
cout << "getdate int t called" << endl;
string tag;
tag = to_string(yr) + to_string(mo) + to_string(da);
return stoi(tag);
}
string getdate(string &str){
cout << "getdate with string as ref" << endl;
return "5/5/55";
}
int getdate(int &myint){
cout << "getdate with int as ref" << endl;
return 12345;
}
void setdate(string dt){
cout << "setdate string dt called " << dt << endl;
mo = 1;
da = 2;
yr = 2020;
}
void setdate(int intdte){
cout << "setdate int to " << intdte << endl;
mo = 99;//any int for now
da = 98;
yr = 1997;
}
void setdate(const char *dte){
cout << "setdate char* dte = " << dte << endl;
mo = 94;
da = 95;
yr = 1996;
}
~Date(){
cout << "destructor called" << endl;
}
//below code permits this in main(): myint = dt;
operator int() {
cout << "operator int()" << endl;
string tag;
tag = to_string(yr) + to_string(mo) + to_string(da);
return stoi(tag);
}
//end section to permit: myint = dt;
//what do I need so I can do this: mystr = dt("mm/dd/yy");, nothing below worked; I tried many more iterations
//than what are shown here
/*
operator string() {
cout << "operator string char" << endl;
return "hello world";
}
string operator = (string &rhs){
cout << "string" << endl;
return "return a string";
}
operator = (const string &rhs){
cout << "will this work?" << endl;
return *this;
}
char& operator = (char(&)[9]){
cout << "whoa, it worked" << endl;
//return "got it";
}
operator = (char*){
cout << "try again" << endl;
}
string operator const char(&)[9] {
cout << "one more time" << endl;
string *ptr;
ptr = "one more time";
return ptr;
}
//end nothing worked to permit me to do this mystr = dte("mm/dd/yy"); section
*/
};//end of class
int main()
{
//create a Date class object dt
Date dt(5, 6, 92);
dt.setdate("02/15/22");
cout << endl;
cout << "next two mystr messages return null because I " << endl;
cout << "can't seem to write a valid overload operator for a literal string" << endl;
string mystr;
//mystr = dt("mm/dd/yy");//does not compile (no match for call to '(Date) (const char [9])'
cout << "mystr using dt(str) = " << mystr << endl;
string myconv = "mm/dd/yy";
//mystr = dt(myconv);//does not compile (no match for call to '(Date) (std::__cxx11::string&)'
cout << "mystr using dt(mm//dd//yy) = " << mystr << endl;
cout << endl;
//this section works
//can I assign dt to an integer (as #days from a reference date)
cout << "this section seems to work" << endl;
int myint;
cout << "myint = dt;" << endl;
myint = dt;//does not compile
cout << "myint (using = dt;) = " << myint << endl;
cout << endl;
system("pause");
}

C++ Delete[] causing program crash [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
My program works fine while I don't have a call to delete[] buf in the destructor. However, when I include it the program crashes at the start of the output.
Here are my files.
//string.cpp
#include "String.h"
#include
#include
extern ofstream csis;
String::String() {
buf = "\0";
length = 0;
}
String::String(const char* tar) {
int temp = strlen(tar);
length = temp;
buf = new char[length + 1];
buf[length] = '\0';
for (int i = 0; i < length; i++){
buf[i] = tar[i];
}
}
String::String(char a) {
length = 1;
buf = new char[length+1];
buf[length] = '\0';
buf[0] = a;
}
String::String(int x) {
int alloc = x;
if (x < 0) {
alloc = 0;
}
buf = new char[alloc+1];
length = x;
buf[0] = '\0';
}
String::String(const String& a) {
length = a.length;
buf = new char[length+1];
for (int i = 0; i < length; i++) {
buf[i] = a.buf[i];
}
}
String::String(char a, int x) {
buf = new char[x+1];
for (int i = 0; i < x; i++) {
buf[i] = a;
}
buf[x] = '\0';
length = strlen(buf);
}
String::~String() {
delete buf;
}
String& String::operator=(const String& tar) {
buf = new char[tar.length+1];
strcpy(buf, tar.buf);
length = tar.length;
buf[length] = '\0';
return *this;
}
String& String::operator=(const char* chr) {
buf = (char*)chr;
length = int(strlen(chr));
return *this;
}
String operator+(const String& a, const String& b) {
String sum;
int size = a.length + b.length;
sum.buf = new char[size+1];
sum.length = size;
for (int i = 0; i < a.length; i++) {
sum.buf[i] = a.buf[i];
}
int j = 0;
for (int i = a.length; i < size; i++) {
sum.buf[i] = b.buf[j];
j++;
}
sum.buf[size] = '\0';
return sum;
}
String operator+(const String& tar, const char* c) {
String sum;
int size = int(strlen(c)) + tar.length;
sum.buf = new char[size+1];
sum.length = size;
for (int i = 0; i < tar.length; i++) {
sum.buf[i] = tar.buf[i];
}
int j = 0;
for (int i = tar.length; i < size; i++) {
sum.buf[i] = c[j];
j++;
}
sum.buf[size] = '\0';
return sum;
}
String operator+(const char* c, const String& tar) {
String sum;
int size = int(strlen(c)) + tar.length;
sum.buf = new char[size+1];
sum.length = size;
for (int i = 0; i < int(strlen(c)); i++) {
sum.buf[i] = c[i];
}
int j = 0;
for (int i = strlen(c); i < size; i++) {
sum.buf[i] = tar.buf[j];
j++;
}
sum.buf[size] = '\0';
return sum;
}
String operator+(const String& tar, char c) {
String sum;
int size = 1 + tar.length;
sum.buf = new char[size];
sum.length = size;
for (int i = 0; i < tar.length; i++) {
sum.buf[i] = tar.buf[i];
}
int j = 0;
for (int i = tar.length; i < size; i++) {
sum.buf[i] = c;
j++;
}
sum.buf[size] = '\0';
return sum;
}
String operator+(char c, const String& tar) {
String sum;
int size = 1 + tar.length;
sum.buf = new char[size+1];
sum.length = size;
for (int i = 0; i < 1; i++) {
sum.buf[i] = c;
}
int j = 0;
for (int i = 1; i < size; i++) {
sum.buf[i] = tar.buf[j];
j++;
}
sum.buf[size] = '\0';
return sum;
}
String& String::operator+=(const String& tar) {
String temp = *this;
temp = temp + tar;
*this = temp;
return *this;
}
String& String::operator+=(const char c) {
String temp = *this;
temp = temp + c;
*this = temp;
return *this;
}
String String::operator+() const {
String sum;
sum.length = length;
sum.buf = new char[sum.length+1];
strcpy(sum.buf, buf);
for (int i = 0; i < length; i++) {
sum.buf[i] = toupper(buf[i]);
}
sum.buf[length] = '\0';
return sum;
}
int operator==(const String & tar, const String& tar2) {
int check = 0;
if (strcmp(tar.buf, tar2.buf) == 0) {
check += 1;
}
else if (strcmp(tar.buf, tar2.buf) != 0) {
check = 0;
}
return check;
}
int operator!=(const String& tar, const String& tar2) {
int check = 0;
if (!(strcmp(tar.buf, tar2.buf) == 0)) {
check += 1;
}
else if (!(strcmp(tar.buf, tar2.buf) != 0)) {
check = 0;
}
return check;
}
int operator<(const String& a, const String& b) {
int check = 0;
if (a.length < b.length) {
check += 1;
}
return check;
}
int operator<=(const String& a, const String& b) {
int check = 0;
if (a.length <= b.length) {
check += 1;
}
return check;
}
int operator>(const String& a, const String& b) {
int check = 0;
if (a.length > b.length) {
check += 1;
}
return check;
}
int operator>=(const String& a, const String& b) {
int check = 0;
if (a.length >= b.length) {
check += 1;
}
return check;
}
char& String::operator[](int x) {
int out;
if (x >= 0 && x < length) {
out = x;
}
else if (!(x >= 0 && x < length)) {
int output = NULL;
cout << "ERROR: Invalid Index with [] operator." << endl;
csis << "ERROR: Invalid Index with [] operator." << endl;
out = NULL;
}
return buf[out];
}
char* operator+(const String& a, int x) {
return &a.buf[x];
}
char* operator+(int x, const String& a) {
return &a.buf[x];
}
String String::operator++(int val) {
String temp;
temp = *this;
for (int i = 0; i < temp.length; i++) {
temp.buf[i] = temp.buf[i] + 1;
}
return temp;
}
String String::operator--(int val) {
String temp;
temp = *this;
for (int i = 0; i < temp.length; i++) {
temp.buf[i] = temp.buf[i] - 1;
}
return temp;
}
String String::operator++() {
String temp = *this;
for (int i = 0; i < temp.length; i++) {
temp.buf[i] = (temp.buf[i] + 1);
}
return temp;
}
String String::operator--() {
String temp = *this;
for (int i = 0; i < temp.length; i++) {
temp.buf[i] = (temp.buf[i] - 1);
}
return temp;
}
int String::getLength() {
return length;
}
String String::substr(int a, int b) {
String temp = *this;
char *fill = new char[b+1];
int i = a;
int x = 0;
while (x <= b) {
fill[i] = temp.buf[i];
i++;
x++;
}
temp.buf = fill;
temp.buf[length] = '\0';
return temp;
}
void String::print() {
cout << """";
csis << """";
for (int i = 0; i < length; i++) {
cout << buf[i];
csis << buf[i];
}
cout << """";
csis << """";
cout << " Length: " << length << endl;
csis << " Length: " << length << endl;
}
ostream& operator<<(ostream& o, const String& tar) {
for (int i = 0; i < tar.length; i++) {
o << tar.buf[i];
}
return o;
}
Here is string.h
//string.h
#ifndef _STRING_H
#define _STRING_H
#include <iomanip>
#include <stdlib.h>
#include <iostream>
using namespace std;
class String {
protected:
int length;
char* buf;
public:
String();
String(const char*);
String(char a);
String(int x);
String(const String&);
String(char a, int x);
~String();
// Operator Overload
String& operator=(const String& tar);
String& operator= (const char*);
friend String operator+(const String& a, const String& b);
friend String operator+(const String&, const char*);
friend String operator+(const char* c, const String& tar);
friend String operator+(const String&, char c);
friend String operator+(char c, const String& tar);
String& operator+=(const String& tar);
String& operator+=(const char c);
String operator+() const;
friend int operator==(const String&, const String&);
friend int operator!=(const String&, const String&);
friend int operator<(const String&, const String&);
friend int operator<=(const String&, const String&);
friend int operator>(const String&, const String&);
friend int operator>=(const String&, const String&);
char& operator[](int);
friend char* operator+(const String&, int);
friend char* operator+(int, const String&);
String operator++();
String operator--();
String operator++(int);
String operator--(int);
int getLength();
String substr(int a, int b);
void print();
friend ostream& operator<<(ostream&, const String&);
};
#endif
Here is StringDriver.cpp
// StringDriver.cpp
// MATTHEW BUTNER
// ID: 011029756
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include "StringDriver.h"
using namespace std;
ofstream csis;
int main() {
csis.open("csis.txt");
test1();
test2();
test3();
test4();
test5();
test6();
test7();
test8();
test9();
test10();
test11();
test12();
test13();
test14();
test15();
test16();
test17();
test18();
test19();
test20();
csis.close();
}
void test1() {
cout << "1. Testing S1: String default ctor." << endl << endl;
csis << "1. Testing S1: String default ctor." << endl << endl;
String s1;
s1.print();
wait();
}
void test2() {
cout << "2. Testing S2: String one arg (char *) ctor." << endl << endl;
csis << "2. Testing S2: String one arg (char *) ctor." << endl << endl;
String s2("ABC");
s2.print();
wait();
}
void test3() {
cout << "3. Testing S3: String one arg (char) ctor." << endl << endl;
csis << "3. Testing S3: String one arg (char) ctor." << endl << endl;
String s3('Z');
s3.print();
wait();
}
void test4() {
cout << "4. Testing S4: String one arg (int) ctor." << endl << endl;
csis << "4. Testing S4: String one arg (int) ctor." << endl << endl;
String s4(10);
s4.print();
wait();
}
void test5() {
cout << "5. Testing S5, T5: String copy ctor." << endl << endl;
csis << "5. Testing S5, T5: String copy ctor." << endl << endl;
String s5("Purple Rain");
s5.print();
String t5(s5);
t5.print();
wait();
}
void test6() {
cout << "6. Testing S6: String two arg (char, int) ctor." << endl << endl;
csis << "6. Testing S6: String two arg (char, int) ctor." << endl << endl;
String s6('*', 10);
s6.print();
wait();
}
void test7() {
cout << "7. Testing S7, T7, U7: String assignment." << endl << endl;
csis << "7. Testing S7, T7, U7: String assignment." << endl << endl;
String s7("Sally Ride"), t7, u7;
t7 = u7 = s7;
s7.print();
t7.print();
u7.print();
wait();
}
void test8() {
cout << "8. Testing S8: String assignment." << endl << endl;
csis << "8. Testing S8: String assignment." << endl << endl;
String s8("ABC");
s8 = s8;
s8.print();
wait();
}
void test9() {
cout << "9. Testing S9: Implicit type conversion." << endl << endl;
csis << "9. Testing S9: Implicit type conversion." << endl << endl;
String s9;
s9 = "ABC";
s9.print();
wait();
}
void test10() {
cout << "10. Testing S10, T10, U10: String concatenation." << endl << endl;
csis << "10. Testing S10, T10, U10: String concatenation." << endl << endl;
String s10("DEF");
String t10('H');
String u10("ABC" + s10 + "G" + t10 + 'I');
u10.print();
String v10('X' + u10);
v10.print();
wait();
}
void test11() {
cout << "11. Testing S11, T11: String concatenation." << endl << endl;
csis << "11. Testing S11, T11: String concatenation." << endl << endl;
String s11('A');
String t11("BC");
s11 += s11 += t11 += 'D';
s11.print();
t11.print();
wait();
}
void test12() {
cout << "12. Testing S12, T12: String unary operator." << endl << endl;
csis << "12. Testing S12, T12: String unary operator." << endl << endl;
String s12("Unary +");
String t12(+s12);
s12.print();
t12.print();
s12 = +s12;
s12.print();
wait();
}
void test13() {
cout << "13. Testing S13, T13: String comparison operators." << endl << endl;
csis << "13. Testing S13, T13: String comparison operators." << endl << endl;
String s13("ABC"), t13("ABCD");
s13.print();
t13.print();
cout << endl;
cout << "== " << (s13 == t13 ? "True" : "False") << endl;
cout << "!= " << (s13 != t13 ? "True" : "False") << endl;
cout << "< " << (s13 < t13 ? "True" : "False") << endl;
cout << "<= " << (s13 <= t13 ? "True" : "False") << endl;
cout << "> " << (s13 > t13 ? "True" : "False") << endl;
cout << ">= " << (s13 >= t13 ? "True" : "False") << endl;
csis << endl;
csis << "== " << (s13 == t13 ? "True" : "False") << endl;
csis << "!= " << (s13 != t13 ? "True" : "False") << endl;
csis << "< " << (s13 < t13 ? "True" : "False") << endl;
csis << "<= " << (s13 <= t13 ? "True" : "False") << endl;
csis << "> " << (s13 > t13 ? "True" : "False") << endl;
csis << ">= " << (s13 >= t13 ? "True" : "False") << endl;
wait();
}
void test14() {
cout << "14. Testing S14: Overloaded subscript operator." << endl << endl;
csis << "14. Testing S14: Overloaded subscript operator." << endl << endl;
String s14("C++ is fun.");
for (int i = -1; i <= s14.getLength(); i++) {
char& ch = s14[i];
if (ch != '\0')
++ch;
}
s14.print();
wait();
}
void test15() {
cout << "15. Testing S15: Pointer notation." << endl << endl;
csis << "15. Testing S15: Pointer notation." << endl << endl;
String s15("ABCDE");
for(int i = 0; i < s15.getLength(); i++)
++(*(s15+i));
for (int j = 0; j < s15.getLength(); j++) {
cout << *(j + s15);
csis << *(j + s15);
}
cout << endl;
csis << endl;
wait();
}
void test16() {
cout << "16. Testing S16, T16, U16, V16, W16, X16, Y16, Z16: Increment and decrement operators." << endl << endl;
csis << "16. Testing S16, T16, U16, V16, W16, X16, Y16, Z16: Increment and decrement operators." << endl << endl;
String s16("ABC");
String t16(++s16);
s16.print();
t16.print();
String u16("ABC");
String v16(u16++);
u16.print();
v16.print();
String w16("ABC");
String x16(--w16);
w16.print();
x16.print();
String y16("ABC");
String z16(y16--);
y16.print();
z16.print();
wait();
}
void test17() {
cout << "17. Testing S17, T17: Substr function." << endl << endl;
csis << "17. Testing S17, T17: Substr function." << endl << endl;
String s17("All You Need Is Love"), t17;
t17 = s17.substr(4, 8);
s17.print();
t17.print();
wait();
}
void test18() {
cout << "18. Testing S18, T18: Output function." << endl << endl;
csis << "18. Testing S18, T18: Output function." << endl << endl;
String s18("Red-");
String t18("Green-");
String u18("Blue");
cout << s18 << t18 << u18;
csis << s18 << t18 << u18;
cout << endl;
csis << endl;
wait();
}
void test19() {
cout << "19. Testing S19, T19, U19: ReverseString class." << endl << endl;
csis << "19. Testing S19, T19, U19: ReverseString class." << endl << endl;
ReverseString s19("Computer");
ReverseString t19;
t19 = ~s19;
s19.print();
t19.print();
ReverseString u19(~~s19);
u19.print();
wait();
}
void test20() {
cout << "20. Testing S20, T20, U20: CaseString class." << endl << endl;
csis << "20. Testing S20, T20, U20: CaseString class." << endl << endl;
CaseString s20("BaLLooN");
CaseString t20;
t20 = s20;
s20.print();
t20.print();
CaseString u20(s20);
u20.print();
wait();
}
void wait() {
char buf;
cout << endl << "Press any key to continue." << endl;
csis << endl << endl;
cin.get(buf);
}
The problem is with the destructor in string.cpp, when I have an empty destructor, everything goes fine and well, but when I include the delete buf, it'll crash the program. Also, here are the other .h and .cpp files:
//ReverseString.h
#ifndef _REVERSESTRING_H
#define _REVERSESTRING_H
#include "String.h"
#include <iostream>
class ReverseString : public String {
public:
ReverseString();
ReverseString(const ReverseString& tar);
ReverseString(const char* c);
ReverseString& operator=(const ReverseString&);
ReverseString operator~();
};
#endif
next file,
//ReverseString.cpp
#include "ReverseString.h"
extern ostream csis;
ReverseString::ReverseString() : String() {
}
ReverseString::ReverseString(const ReverseString& tar) : String(tar) {
}
ReverseString::ReverseString(const char* c) : String(c) {
}
ReverseString& ReverseString::operator=(const ReverseString& tar) {
length = tar.length;
buf = tar.buf;
buf[length] = '\0';
return *this;
}
ReverseString ReverseString::operator~() {
ReverseString reverse;
reverse.length = length;
reverse.buf = new char[length];
int j = length - 1;
for (int i = 0; i < length; i++) {
reverse.buf[i] = buf[j];
j--;
}
return reverse;
}
CaseString.h
#ifndef _CASESTRING_H
#define _CASESTRING_H
#include "String.h"
#include <iostream>
class CaseString : public String {
protected:
char* upper;
char* lower;
public:
CaseString();
CaseString(const CaseString& tar);
CaseString(const char* c);
CaseString& operator=(const CaseString& c);
void print();
~CaseString();
};
#endif
CaseString.cpp
#include "CaseString.h"
#include <fstream>
extern ofstream csis;
CaseString::CaseString() : String() {
}
CaseString::CaseString(const CaseString& tar) : String(tar) {
upper = tar.upper;
lower = tar.lower;
buf = tar.buf;
length = tar.length;
}
CaseString::CaseString(const char* c) : String(c) {
lower = new char[int(strlen(c))];
upper = new char[int(strlen(c))];
int losize = strlen(c);
char* getLow = new char[losize];
for (int i = 0; i < losize; i++) {
getLow[i] = tolower(c[i]);
}
char* getHi = new char[losize];
for (int i = 0; i < losize; i++) {
getHi[i] = toupper(c[i]);
}
lower = getLow;
upper = getHi;
lower[losize] = '\0';
upper[losize] = '\0';
}
CaseString& CaseString::operator=(const CaseString& tar) {
if (&tar != this) {
String::operator=(tar);
buf = tar.buf;
length = tar.length;
lower = tar.lower;
upper = tar.upper;
}
return *this;
}
void CaseString::print() {
cout << "\"" << buf << "\"" << " " << "Length = " << length << " |" << "Lower = " << lower << " |" << "Upper = " << upper << endl;
csis << "\"" << buf << "\"" << " |" << "Length = " << length << " |" << "Lower = " << lower << " |" << "Upper = " << upper << endl;
}
CaseString::~CaseString() {
}
There are several issues that I see.
The main problem is that you sometimes assign a pointer to a character string to buf (your default constructor is one such place, and there is at least one other). This is a pointer you do not want to delete. You need to either always allocate memory for buf, or have some way to tell if you own the pointer and it should be deleted.
The other issue is that since you use new [], you need to use delete [] buf in your destructor.
In your copy constructor, you do not copy the nul byte at the end of the coped buffer.

non-helper << operator not working C++

I'm trying to overload the << operator for the display function call.
Heres my code:
#include <iostream>
#include <cstring>
using namespace std;
// global variable
const int MAX = 3;
// class definition
class CString{
char str[MAX+1];
public:
CString(char* param){
if(param == nullptr){
str[0] = '\0';
return;
}
strncpy(str,param,MAX);
str[MAX] = '\0';
}
void display(ostream& os){
os << str;
}
};
// << operator overloading
ostream& operator << (ostream& os, CString& cs){
static int call = 0;
os << call << ": ";
cs.display(os);
call++;
return os;
}
void process(char* parm){
CString cs(parm);
// here is where my issue is
cs.display(cout);
cout << endl;
}
//----------------------------------------------------------------
int main(int argc,char *argv[]){
cout << "Command Liine : ";
for(int arg = 0; arg < argc ; arg++){
cout << " " << argv[arg];
}
cout << endl;
if( argc == 1){
cout << "Insufffiecentnumber of arguemnts (min1)" << endl;
return 1;
}
cout << " Maxium numver of characters stored: " << MAX << endl;
for(int arg = 1; arg < argc; arg++){
process(argv[arg]);
}
return 0;
}
EDIT:
Here is the correct output and the output I have:
Correct:
Command Line : w1 oop345 btp305
Maximum number of characters stored : 3
0: oop
1: btp
Mine:
Command Line : w1 OOP345 DBS305
Maxium number of characters stored: 3
OOP
DBS
I'm having an issue with my << operator not working, I can't seem to figure it out. The ostream& operator<<(ostream& os, CString& cs) does not seem to be loading its syntax.
Question:
Does anyone know where my mistake has been made?
You wrote a correct overloading of << operator, but in method process() you used a public method display() of class CString instead of using << operator directly.
Just change one line in method process():
cs.display(cout); to: cout << cs;
void process(char* parm){
CString cs(parm);
// here is where my issue is
cout << cs;
cout << endl;
}
P.S. you do not need method CString::display at all as you already overload << operator for this class.

Segmentation Fault (Core Dump) - Code works in VS but not in the Linux Terminal [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
So, I can run this program in Visual Studio with absolutely no problems, producing correct output. However, after compiling in the Linux terminal, I get a seg fault when trying to run the same code. Upon debugging using GDB, the information given is not very helpful (will be provided below). The program consists of two header files and three .cpp files. I will provide all of them below, along with the debugging information given. (If the indenting is weird, it is because of the 4-space code indent rule for submission). I have been trying to find the issue for hours on end to no avail. I have a feeling it is a small, minor mistake. Thank you all very much in advance.
Song.h
#ifndef Song_h
#define Song_h
#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
#include <stdlib.h>
using namespace std;
class Song
{
private:
string artist;
string title;
int size;
public:
Song(); //declares blank song array
Song(string _title, string _artist, int _size); //initializes object with given parameters for Song instance
string getArtist() const
{
return artist;
}
string getTitle() const
{
return title;
}
int getSize() const
{
return size;
}
void setArtist(string _artist)
{
artist = _artist;
}
void setTitle(string _title)
{
title = _title;
}
void setSize(int _size)
{
size = _size;
}
bool operator == (Song const &rhs);
bool operator != (Song const &rhs);
bool operator > (Song const &rhs);
bool operator < (Song const &rhs);
};
#endif
TsuPod.h
#ifndef TsuPod_h
#define TsuPod_h
#include "Song.h"
//TsuPod class declaration
class TsuPod
{
private:
struct SongNode
{
Song data;
SongNode *next;
};
SongNode *songs; //the head pointer
static const int MAX_SIZE = 512;
static const int SUCCESS = 0;
static const int FAILURE = 1;
static const int NO_MEMORY = -1;
static const int NOT_FOUND = -2;
int getNumSongs();
int memSize;
public:
TsuPod();
TsuPod(int size);
~TsuPod();
int addSong(Song const &s);
int removeSong(Song const &s);
void shuffle();
void showSongList();
void sortSongList();
int getRemainingMemory();
int getTotalMemory()
{
return memSize;
}
};
Song.cpp
#endif
#include "TsuPod.h"
#include "Song.h"
Song::Song() //default constructor, initializes a blank song
{
artist = "";
title = "";
size = 0;
}
Song::Song(string _artist, string _title, int _size) //constructor for song when arguments are given by user
{
artist = _artist;
title = _title;
size = _size;
}
bool Song::operator == (Song const &rhs) //overloaded for sorting
{
return (title == rhs.title &&
artist == rhs.artist &&
size == rhs.size);
}
bool Song::operator != (Song const &rhs) //overloaded for sorting
{
return (title != rhs.title ||
artist != rhs.artist ||
size != rhs.size);
}
bool Song::operator > (Song const &rhs) //overloaded for sorting
{
if (artist != rhs.artist)
return (artist > rhs.artist);
else
if (title != rhs.title)
return (title > rhs.title);
else
if (size != rhs.size)
return (size > rhs.size);
else
return false;
}
bool Song::operator < (Song const &rhs) //overloaded for sorting
{
if (artist != rhs.artist)
return (artist < rhs.artist);
else
if (title != rhs.title)
return (title < rhs.title);
else
if (size != rhs.size)
return (size < rhs.size);
else
return false;
}
TsuPod.cpp
#include "TsuPod.h"
#include "Song.h"
TsuPod::TsuPod() //default constructor
{
memSize = MAX_SIZE;
}
TsuPod::TsuPod(int _size) //constructor for when user specifies their prefered memory size, prevents input of a size greater than MAX_SIZE or less than 0
{
if (_size > MAX_SIZE || _size <= 0)
memSize = MAX_SIZE;
else
memSize = _size;
}
TsuPod::~TsuPod() //destructor
{
SongNode *p;
while (songs != NULL)
{
p = songs;
songs = songs->next;
delete p;
}
}
int TsuPod::getRemainingMemory() //finds remaining memory, returns int value
{
int memSum = 0;
SongNode *p = songs;
while (p != NULL)
{
memSum += p->data.getSize();
p = p->next;
}
return memSize - memSum;
}
int TsuPod::addSong(Song const &s) //adds song to TsuPod, returns int number to display result, 0 = success, 1 = failure, -1 = not enough memory
{
if (s.getSize() > getRemainingMemory()) //ensures there is enough unsused memory for song
return NO_MEMORY;
if (s.getSize() > 0) //ensures song is valid
{
SongNode *temp = new SongNode;
temp->data = s;
temp->next = songs;
songs = temp;
return SUCCESS;
}
else
return FAILURE;
}
int TsuPod::removeSong(Song const &s) //removes song, returns int value to display result, 0 = success, 1 = failure, -2 = not found
{
if (songs != NULL)
{
SongNode *prev = NULL;
SongNode *p = songs;
if (p->data == s)
{
songs = p->next;
return SUCCESS;
}
while (p != NULL && p->data != s)
{
prev = p;
p = p->next;
if (songs->data == s)
{
songs = p->next;
delete p;
return SUCCESS;
}
else
if (p->data == s)
{
prev->next = p->next;
delete p;
return SUCCESS;
}
else
{
}
}
}
return NOT_FOUND;
}
int TsuPod::getNumSongs() //calculates number of songs, returns int value
{
SongNode *p1 = songs;
int i = 0;
while (p1 != NULL)
{
i++;
p1 = p1->next;
}
return i;
}
void TsuPod::shuffle() //shuffles TsuPod song list, void return value
{
srand((unsigned)time(NULL));
for (int j = 0; j < getNumSongs() * 2; j++)
{
int r1 = rand() % getNumSongs();
int r2 = rand() % getNumSongs();
SongNode *p1 = songs;
SongNode *p2 = songs;
for (int i = 0; i < r1; i++)
p1 = p1->next;
for (int i = 0; i < r2; i++)
p2 = p2->next;
Song temp = p1->data;
p1->data = p2->data;
p2->data = temp;
}
cout << endl << " PLAYLIST SHUFFLED" << endl << endl;
}
void TsuPod::sortSongList() //sorts song list by artist, title, and size respectively, void return value
{
for (SongNode *p1 = songs; p1 != NULL; p1 = p1->next)
{
SongNode *small = p1;
for (SongNode *p2 = p1->next; p2 != NULL; p2 = p2->next)
{
if (small->data > p2->data)
{
small = p2;
}
}
if (p1 != small)
{
Song temp = small->data;
small->data = p1->data;
p1->data = temp;
}
}
cout << endl << " PLAYLIST SORTED" << endl;
}
void TsuPod::showSongList() //shows song list, void return value
{
cout << " ___________________________________________________ " << endl << " TsuPod 2.0" << endl << endl;
cout << " Memory ---- Total: " << getTotalMemory() << " MB" << " -- Remaining: " << getRemainingMemory() << " MB" << endl;
SongNode *p = songs;
int i = 0;
while (p != NULL)
{
i++;
cout << endl << " " << i << ". " << p->data.getArtist();
int artistLength = p->data.getArtist().length();
for (int j = 0; j < (24 - artistLength); j++) //This loop is implemented to evenly space the artist from the song
cout << " ";
cout << p->data.getTitle();
int titleLength = p->data.getTitle().length();
for (int j = 0; j < (24 - titleLength); j++) //This loop is implemented to evenly space the song title from the song size
cout << " ";
cout << p->data.getSize() << " (MB)" << endl;
p = p->next;
}
cout << endl;
}
TsuPod_Driver.cpp
#include <cstdlib>
#include <iostream>
#include "Song.h"
#include "TsuPod.h"
using namespace std;
int main(int argc, char *argv[])
{
TsuPod t;
Song s1("Animals As Leaders", "Another Year", 4);
int result = t.addSong(s1);
cout << " add result = " << result << endl;
Song s2("Gorillaz", "Stylo", 6);
result = t.addSong(s2);
cout << " add result = " << result << endl;
Song s3("August Burns Red", "Meridian", 6);
result = t.addSong(s3);
cout << " add result = " << result << endl;
Song s4("The Ink Spots", "If I Didn't Care", 7);
result = t.addSong(s4);
cout << " add result = " << result << endl;
Song s5("Beatles", "I Feel Fine", 241);
result = t.addSong(s5);
cout << " add result = " << result << endl;
Song s6("Fine Constant", "Sea", 3);
result = t.addSong(s6);
cout << " add result = " << result << endl;
Song s7("Human Abstract", "Nocturne", 9);
result = t.addSong(s7);
cout << " add result = " << result << endl;
Song s8("August Burns Red", "Meridian", 4);
result = t.addSong(s8);
cout << " add result = " << result << endl;
Song s9("Frank Sinatra", "My Way", 5);
result = t.addSong(s9);
cout << " add result = " << result << endl;
t.showSongList();
t.shuffle();
t.showSongList();
t.sortSongList();
t.showSongList();
result = t.removeSong(s1);
cout << " delete result = " << result << endl;
result = t.removeSong(s2);
cout << " delete result = " << result << endl;
result = t.removeSong(s3);
cout << " delete result = " << result << endl;
t.showSongList();
result = t.removeSong(s4);
cout << " delete result = " << result << endl;
result = t.removeSong(s5);
cout << " delete result = " << result << endl;
result = t.removeSong(s6);
cout << " delete result = " << result << endl;
result = t.removeSong(s7);
cout << " delete result = " << result << endl;
result = t.removeSong(s8);
cout << " delete result = " << result << endl;
result = t.removeSong(s9);
cout << " delete result = " << result << endl;
t.showSongList();
cout << " memory = " << t.getRemainingMemory() << endl << endl << endl << endl;
for (int i = 1; i < 33; i++) //tests to ensure that user cannot add a song when there is not enough space available
{
Song s1("August Burns Red", "Meridian", i);
result = t.addSong(s1);
cout << " add result = " << result << endl;
}
t.showSongList();
cin.get();
return EXIT_SUCCESS;
Debugging Info From Linux Terminal
Program received signal SIGSEGV, Segmentation fault.
0x0000000000402d50 in Song::getSize() const ()
(gdb) backtrace
#0 0x0000000000402d50 in Song::getSize() const ()
#1 0x00000000004024ac in TsuPod::getRemainingMemory() ()
#2 0x00000000004024fb in TsuPod::addSong(Song const&) ()
#3 0x000000000040112e in main ()
I don't see any sign of TsuPod::songs being initialized. There is no guarantee that it's going to be NULL in the empty list case, so your
while (p != NULL)
test in TsuPod::getRemainingMemory() may pass with an insane value from the stack and blow up when you use p on the next line.
I recommend
TsuPod::TsuPod():songs(NULL) //default constructor
{
memSize = MAX_SIZE;
}
TsuPod::TsuPod(int _size):songs(NULL) //constructor for when user specifies their prefered memory size, prevents input of a size greater than MAX_SIZE or less than 0
{
if (_size > MAX_SIZE || _size <= 0)
memSize = MAX_SIZE;
else
memSize = _size;
}
to ensure that songs starts with your end of list condition.
Also, consider using std::list to do your list management in place of the roll-your-own linked list.