I'm trying to concatenate two arrays and at the end concatenate int, for example: result = arg + arg + 2;
I'm getting "read access violation" at + operator overloading.
I wrote the error and warning in comments below.
My code:
Main:
#include <iostream>
#include <string>
#include "CTable.h"
int main() {
CTable c_tab1, c_tab0;
c_tab0.SetNewSize(3);
c_tab1.SetNewSize(2);
c_tab0.SetValueAt(0, 22);
c_tab0.SetValueAt(1, 23);
c_tab0.SetValueAt(2, 24);
c_tab0.Print();
c_tab1.SetValueAt(0, 31);
c_tab1.SetValueAt(1, 32);
c_tab1.Print();
CTable c_tab3 = (c_tab0 + c_tab1 + 111);
c_tab3.Print();
return 0;
}
Class CTable:
#include <iostream>
#include <string>
using namespace std;
class CTable {
public:
CTable();
CTable(string sName, int iTableLen);
CTable(const CTable& pcOther);
CTable* pcClone();
~CTable();
void ShowName();
void ShowSize();
void SetName(string sName);
bool SetNewSize(int iTableLen);
void SetValueAt(int iOffset, int iNewVal);
void Print();
CTable& operator+(const CTable& pcNewTable);
CTable operator+(int iNewVal) const;
CTable& operator=(const CTable& pcNewVal) {
if (this != &pcNewVal) {
for (int i = 0; i < i_size; i++) {
this->piTable[i] = pcNewVal.piTable[i];
}
}
return *this;
}
private:
string s_name;
int i_size;
int* piTable;
const int SIZE = 10;
const string NAME = "Name";
};
#include <iostream>
#include <string>
#include "CTable.h"
#include <algorithm>
using namespace std;
CTable::CTable() {
s_name = NAME;
cout << "bezp: " << s_name << endl;
piTable = new int[SIZE];
i_size = SIZE;
}
CTable::CTable(string sName, int iTableLen) {
s_name = sName;
cout << "parametr: " << sName << endl;
piTable = new int[iTableLen];
i_size = iTableLen;
}
CTable::CTable(const CTable& pcOther) {
s_name = pcOther.s_name + "copied";
piTable = new int[pcOther.i_size];
i_size = pcOther.i_size;
for (int i = 0; i < pcOther.i_size; i++) {
piTable[i] = pcOther.piTable[i];
}
}
CTable::~CTable() {
delete[] piTable;
}
void CTable::SetName(string sName) {
s_name = sName;
}
bool CTable::SetNewSize(int iTableLen) {
if (iTableLen <= 0) {
cout << "Length has to be greater than 0" << endl;
return false;
}
int* pi_newTable = new int[iTableLen];
for (int i = 0; i < iTableLen; i++) {
pi_newTable[i] = piTable[i];
}
delete this->piTable;
this->i_size = iTableLen;
this->piTable = pi_newTable;
return true;
}
CTable* CTable::pcClone() {
CTable* ct = new CTable(s_name, i_size);
return ct;
}
void CTable::ShowName() {
cout << "Name: " << s_name << endl;
}
void CTable::ShowSize() {
cout << "Size: " << i_size << endl;
}
void CTable::SetValueAt(int iOffset, int iNewVal) {
if (iOffset >= this->i_size) {
return;
}
piTable[iOffset] = iNewVal;
}
void CTable::Print() {
for (int i = 0; i < i_size; i++) {
cout << piTable[i] << " ";
}
cout << endl;
}
CTable& CTable::operator+(const CTable& pcNewTable) {
CTable result("new_int", this->i_size);
result.i_size = (i_size + pcNewTable.i_size);
result.piTable = new int[i_size + pcNewTable.i_size];
for (int i = 0; i < i_size; i++) {
result.piTable[i] = piTable[i];
}
for (int i = 0; i < (pcNewTable.i_size); i++) {
result.piTable[i+i_size] = pcNewTable.piTable[i];
}
return result; //Warning C4172 returning address of local variable or temporary: result
}
CTable CTable::operator+(int iNewVal) const {
CTable result("new_int", this->i_size);
result.i_size = (i_size + 1);
result.piTable = new int[i_size + 1];
for (int i = 0; i < i_size; i++) {
result.piTable[i] = piTable[i]; //Exception thrown: read access violation. **this->piTable** was 0x1110122.
}
result.piTable[i_size + 1] = iNewVal;
return result;
}
What should I correct? I'm not sure about assigment operator overload, is it okay?
The member function SetNewSize has undefined behavior. In this loop
int* pi_newTable = new int[iTableLen];
for (int i = 0; i < iTableLen; i++) {
pi_newTable[i] = piTable[i];
}
it 1) uses uninitialized values because the array was not initialized and 2) iTableLen can be gretaer than the current value of i_size. You should at least zero initialize the array in constructors.
The copy assignment operator aslo has undefined behabior because the number of elements of the array of the object pcNewVal can be less than the number of elements of the array in the assigned object.
The first overloaded operator + also have undefined behavior. For starters as the warning says the operator returns reference to the local object result that will not be alive after exiting the operator. Secondly, there is a memory leak necause the array of the object is allocated anew and the previuous allocated memory in the constructor is not freed.
CTable result("new_int", this->i_size);
result.i_size = (i_size + pcNewTable.i_size);
result.piTable = new int[i_size + pcNewTable.i_size];
//...
The second overloaded operator + also has undefined behavior. As in the previous operator there is a memory leak.
In this statement
result.piTable[i_size + 1] = iNewVal;
there is an access memory outside the allocated array. There should be
result.piTable[i_size] = iNewVal;
I made a dynamic array with template. The problem is that when I don't keep there pointers (for example: Tab<string> da;) my destructor doesn't have to clear it and throws error caused by delete arr[i];. My question is if I can put some if condition(in which I would put clear() method) which would tell me if my array keeps pointers. In the simplest way I can use clear() in main when I keeps there pointers, but my teacher wants me to make it like I wrote above.
I tried using is_pointer, but it doesn't work or I use it wrong.
Any suggestions?
#ifndef TABLICA_H
#define TABLICA_H
#include <iostream>
#include <type_traits>
using namespace std;
template<class T>
class Tab
{
public:
int size = 0;
int max_size = 1;
T* arr;
bool isDynamic = false;
Tab()
{
arr = new T[max_size];
}
~Tab()
{
clear();
delete[] arr;
}
void check_size()
{
if (size == max_size)
{
max_size = max_size * 2;
T* arr2 = new T[max_size];
for (int i = 0; i < size; i++)
{
arr2[i] = arr[i];
}
delete[] arr;
arr = arr2;
}
}
void push_back(const T& value)
{
check_size();
arr[size] = value;
size++;
}
T return_by_index(int index)
{
if (index<0 || index > size)
{
return NULL;
}
return arr[index];
}
bool replace(int index, const T& value)
{
if (index<0 || index > size)
{
return false;
}
arr[index] = value;
return true;
}
void print(int number)
{
cout << "Rozmiar obecny: " << size << endl;
cout << "Rozmiar maksymalny: " << max_size << endl;
cout << "Adres tablicy: " << arr << endl;
cout << "Kilka poczatkowych elementow tablicy " << "(" << number << ")" << endl;
for (int i = 0; i < number; i++)
{
cout << *arr[i] << endl;
}
}
void clear()
{
for (int i = 0; i < size; i++)
{
delete arr[i];
}
}
};
#endif
//Source:
#include <iostream>
struct object
{
int field1;
char field2;
object()
{
field1 = rand() % 10001;
field2 = rand() % 26 + 'A';
}
};
ostream& operator<<(ostream& out, const object& o)
{
return out << o.field1 << " " << o.field2;
}
int main()
{
Tab < object* >* da = new Tab < object* >();
delete da;
system("PAUSE");
return 0;
I tried everything and looked everywhere but I keep getting
Exception thrown: read access violation.
**_Right_data was 0x4.**
What is wrong with the code? I am not very good with C++ and don't like it at all but working on this school project and trying to figure out why I get the exception. Any help is appreciated
#include "Roster.h"
#include "Student.h"
#include "NetworkStudent.h"
#include "SecurityStudent.h"
#include "SoftwareStudent.h"
#include <iostream>
#include <string>
#include<vector>
#include<sstream>
#include<regex>
// Separates Data on basis of ,
template <class Container>
void splitString(const std::string& str, Container& cont)
{
char delim = ',';
std::stringstream ss(str);
std::string token;
while (std::getline(ss, token, delim)) {
cont.push_back(token);
}
}
// Checks and returns if email is valid or not
bool Email(std::string email)
{
const std::regex pattern("(\\w+)(\\.|_)?(\\w*)#(\\w+)(\\.(\\w+))+");
return regex_match(email, pattern);
}
// Main Function
int main()
{
Roster classRoster;
// Data Array
const std::string studentData[] = { "A1,John,Smith,John1989#gm ail.com,20,30,35,40,SECURITY",
"A2,Suzan,Erickson,Erickson_1990#gmailcom,19,50,30,40,NETWORK",
"A3,Jack,Napoli,The_lawyer99yahoo.com,19,20,40,33,SOFTWARE",
"A4,Erin,Black,Erin.black#comcast.net,22,50,58,40,SECURITY",
};
for (unsigned int i = 0;i < 5;i++)
{
std::vector<std::string> words;
std::string s = studentData[i];
// Splits Input
splitString(s, words);
// if Student belongs to Security
if (words.at(8) == "SECURITY")
{
int a[3] = { stoi(words.at(5)),stoi(words.at(6)),stoi(words.at(7)) };
classRoster.classRosterArray[i] = new SecurityStudent(words.at(0), words.at(1), words.at(2), words.at(3), stoi(words.at(4)), a, SECURITY);
}
// IF Student Belongs to Software
else if (words.at(8) == "SOFTWARE")
{
int a[3] = { stoi(words.at(5)),stoi(words.at(6)),stoi(words.at(7)) };
classRoster.classRosterArray[i]=new SoftwareStudent(words.at(0), words.at(1), words.at(2), words.at(3), stoi(words.at(4)), a, SOFTWARE);
}
// If Student Belongs to Network
else if (words.at(8) == "NETWORK")
{
int a[3] = { stoi(words.at(5)),stoi(words.at(6)),stoi(words.at(7)) };
classRoster.classRosterArray[i] = new NetworkStudent(words.at(0), words.at(1), words.at(2), words.at(3), stoi(words.at(4)), a, NETWORK);
}
}
std::cout << "\n---------Print All Student's Data------------\n";
classRoster.printAll();
std::cout << "\n---------------------------------------------\n";
std::cout << "Invalid Emails\n";
classRoster.printInvalidEmails();
std::cout << "\n--------------Days in Course------------------\n";
classRoster.printDaysInCourse("A2");
std::cout << "\n--------------By Degree Program------------------";
classRoster.printByDegreeProgram(3);
std::cout << "\n--------------Removes A3------------------\n";
classRoster.remove("A3");
classRoster.remove("A3");
return 0;
}
// Adds Student to Roster
void Roster::add(std::string studentID, std::string firstName, std::string lastName, std::string emailAddress, int age, int daysInCourse1, int daysInCourse2, int daysInCourse3, degree d)
{
if (d == SOFTWARE)
{
delete classRosterArray[4];
int a[3] = { daysInCourse1,daysInCourse2,daysInCourse3 };
classRosterArray[4] = new SoftwareStudent(studentID, firstName, lastName, emailAddress, age,a, d);
}
else if (d == NETWORK)
{
delete classRosterArray[4];
int a[3] = { daysInCourse1,daysInCourse2,daysInCourse3 };
classRosterArray[4] = new NetworkStudent(studentID, firstName, lastName, emailAddress, age, a, d);
}
else if (d == SECURITY)
{
delete classRosterArray[4];
int a[3] = { daysInCourse1,daysInCourse2,daysInCourse3 };
classRosterArray[4] = new SecurityStudent(studentID, firstName, lastName, emailAddress, age, a, d);
}
}
// Removes Student
void Roster::remove(std::string studentID)
{
for (unsigned i = 0;i < 5;i++)
{
if (classRosterArray[i]->getStudentID() == studentID){
std::cout << "STUDENT REMOVED " << classRosterArray[i]->getStudentID()<<"\n";
classRosterArray[i] = NULL;
}
}
std::cout << "Student ID Does not Exist \n";
}
// Prints All Data Of Array
void Roster::printAll()
{
for (unsigned i = 0;i < 5;i++)
{
std::cout << i + 1 << "\t";
classRosterArray[i]->print();
std::cout << "\n";
}
}
// Prints Average Days in Course for a specific Student
void Roster::printDaysInCourse(std::string studentID)
{
int sum = 0;
for (unsigned i = 0;i < 5;i++)
{
if (classRosterArray[i]->getStudentID() == studentID)
{
int *p = classRosterArray[i]->getStudentDaysofCourses();
for (unsigned int j = 0;j < 3;j++)
sum += p[j];
delete[]p;
break;
}
}
std::cout << sum / 3.0;
}
// Prints Invalid Emails
void Roster::printInvalidEmails()
{
for (unsigned i = 0;i < 5;i++)
{
std::string email = classRosterArray[i]->getStudentEmail();
if (!Email(email))
{
std::cout << classRosterArray[i]->getStudentEmail();
//classRosterArray[i]->print();
std::cout << "\n";
}
}
}
// Prints By Degree Program
void Roster::printByDegreeProgram(int degreeProgram)
{
for (unsigned i = 0;i < 5;i++)
{
if (classRosterArray[i]->getDegreeProgram()==degreeProgram)
classRosterArray[i]->print();
std::cout << "\n";
}
}
// Destructor
Roster::~Roster()
{
for (unsigned i = 0; i < 5; i++)
{
if (classRosterArray[i]!=NULL)
delete classRosterArray[i];
}
}
Figured it out!
This part was causing the error
// Removes Student
void Roster::remove(std::string studentID)
{
for (unsigned i = 0;i < 5;i++)
{
if (classRosterArray[i]->getStudentID() == studentID){
std::cout << "STUDENT REMOVED " << classRosterArray[i]->getStudentID()<<"\n";
classRosterArray[i] = NULL;
}
}
std::cout << "Student ID Does not Exist \n";
}
Changed to
// Removes Student
void Roster::remove(std::string studentID)
{
for (unsigned i = 0; i < 5; i++)
{
if (classRosterArray[i] != NULL && classRosterArray[i]->getStudentID() == studentID) {
std::cout << "STUDENT REMOVED " << classRosterArray[i]->getStudentID() << "\n";
delete classRosterArray[i];
classRosterArray[i] = NULL;
return;
}
}
std::cout << "Student ID Does not Exist \n";
}
I am writing a code using classes and am getting the wrong output, this is my function definitions:
void PrintCard(int c)
{
int Rank = c%13;
int Suit = c/13;
const char NameSuit[5] = "SCDH";
const char NameRank[14] = "23456789XJQKA";
cout << NameRank[Rank] << NameSuit[Suit];
}
CardSet::CardSet()
{
Card = NULL;
nCards = 0;
}
CardSet::CardSet(int c)
{
Card = new int[c];
for(int i = 0; i > c; i++)
{
Card[i] = (i % 52);
}
}
CardSet::~CardSet()
{
delete[] Card;
}
bool CardSet::IsEmpty() const
{
return nCards == 0;
}
void CardSet::Print() const
{
for(int i=0; i > nCards; i++)
{
PrintCard(i);
}
}
int CardSet::Size() const
{
return nCards;
}
This is my main
cout << "Testing constructors, Print(), Size() & IsEmpty():" << endl;
CardSet CardSet1; // empty cCardSet
CardSet CardSet2(12); // CardSet with 12 cards
if(CardSet1.IsEmpty()) cout<<"CardSet1 is empty"<<endl;
else cout<<"CardSet1 has "<< CardSet1.Size() <<" cards" << endl;
if(CardSet2.IsEmpty()) cout<<"CardSet2 is empty"<<endl;
else cout<<"CardSet2 has "<< CardSet2.Size() <<" cards" << endl;
cout << "Printout of CardSet1: ";
CardSet1.Print();
cout << "Printout of CardSet2: ";
CardSet2.Print();
cout << endl;
when i am compiling i am getting the correct value (0) for cardset1 however for cardset2 instead of outputting a value of 12, which is what should be the output i am getting very high numbers that are changing each time i compile. i think something is wrong with my for loops or memory allocation.
this is also what the class definition looks like:
class CardSet
{
public:
CardSet();
CardSet(int);
~CardSet();
int Size() const;
bool IsEmpty() const;
void Shuffle();
int Deal();
void Deal(int,CardSet&,CardSet&);
void Deal(int,CardSet&,CardSet&,CardSet&,CardSet&);
void AddCard(int);
void MergeShuffle(CardSet&);
void Print() const;
private:
int* Card;
int nCards;
};
any help would be greatly appreciated !!
Cheers
In CardSet::CardSet change this
for(int i = 0; i > c; i++)
to this
for (int i = 0; i < c; i++)
Also in CardSet::Print change this
for(int i=0; i > nCards; i++)
To this:
for (int i = 0; i < nCards; i++)
Finally, add nCards = c; to CardSet::CardSet.
void CardSet::Print() const
{
for(int i=0; i > nCards; i++)
{
PrintCard(i);
}
}
must be
void CardSet::Print() const
{
for(int i=0; i < nCards; i++)
{
PrintCard(i);
}
}
to correct the end test, and you have the same problem in CardSet::CardSet(int c) which must be
CardSet::CardSet(int c)
{
nCards = c;
Card = new int[c];
for(int i = 0; i < c; i++)
{
Card[i] = (i % 52);
}
}
where nCards must also be set.
In a for the test indicates if the loop continues, not if it ends
for (inits; test; changes) ...
is equivalent to
init;
while (test) {
...
changes;
}
Out of that there is no separator in PrintCard doing cout << NameRank[Rank] << NameSuit[Suit]; so may be you also need to add something like a space in Print :
void CardSet::Print() const
{
for(int i=0; i < nCards; i++)
{
PrintCard(i);
cout << ' ';
}
}
or in PrintCard to also separate the two fields like
cout << NameRank[Rank] << ' ' << NameSuit[Suit] << endl;
Note you can simplify
const char NameSuit[5] = "SCDH";
const char NameRank[14] = "23456789XJQKA";
cout << NameRank[Rank] << NameSuit[Suit];
to be
cout << "23456789XJQKA"[Rank] << "SCDH"[Suit];
Or if you really want to have the arrays I encourage you to not give a size, that avoid problems if you change the literal string and forget to also change the size, so
const char NameSuit[] = "SCDH";
const char NameRank[] = "23456789XJQKA";
For instance having :
#include <iostream>
using namespace std;
class CardSet
{
public:
CardSet();
CardSet(int);
~CardSet();
int Size() const;
bool IsEmpty() const;
void Shuffle();
int Deal();
void Deal(int,CardSet&,CardSet&);
void Deal(int,CardSet&,CardSet&,CardSet&,CardSet&);
void AddCard(int);
void MergeShuffle(CardSet&);
void Print() const;
private:
int* Card;
int nCards;
};
void PrintCard(int c)
{
int Rank = c%13;
int Suit = c/13;
cout << "23456789XJQKA"[Rank] << ' ' << "SCDH"[Suit] << endl;
}
CardSet::CardSet()
{
Card = NULL;
nCards = 0;
}
CardSet::CardSet(int c)
{
nCards = c;
Card = new int[c];
for(int i = 0; i < c; i++)
{
Card[i] = (i % 52);
}
}
CardSet::~CardSet()
{
delete[] Card;
}
bool CardSet::IsEmpty() const
{
return nCards == 0;
}
void CardSet::Print() const
{
for(int i=0; i < nCards; i++)
{
PrintCard(i);
}
}
int CardSet::Size() const
{
return nCards;
}
int main(void)
{
CardSet cs(5);
cs.Print();
}
Compilation and execution :
pi#raspberrypi:/tmp $ g++ -pedantic -Wall -Wextra c.cc
pi#raspberrypi:/tmp $ ./a.out
2 S
3 S
4 S
5 S
6 S
pi#raspberrypi:/tmp $
You should review it (the loop)
void CardSet::Print() const
{
for(int i=0; i > nCards; i++)//## reconsider it
{
PrintCard(i);
}
}
I am fairly new to dynamic memory allocation and am having trouble. I'm thinking the problem is within my allocation function but I could be wrong. Here is the MyString.cpp file.
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "MyString.h"
using namespace std;
MyString::MyString()
{
m_size = 0;
buffer_allocate(0);
}
MyString::MyString(const char * str)
{
m_size = strlen(str);
buffer_allocate(m_size);
for(int i = 0; i < m_size; i++)
{
m_buffer[i] = str[i];
}
}
MyString::MyString(const MyString & other_myStr)
{
m_size = other_myStr.size();
buffer_allocate(other_myStr.size());
for(int i = 0; i < other_myStr.size(); i++)
{
m_buffer[i] = other_myStr.c_str()[i];
}
}
void MyString::buffer_deallocate()
{
delete[] m_buffer;
m_size = 0;
}
void MyString::buffer_allocate(size_t size)
{
try
{
m_buffer = new char[size];
}
catch(bad_alloc& ex)
{
delete[] m_buffer;
}
}
MyString::~MyString()
{
buffer_deallocate();
}
size_t MyString::size() const
{
return m_size;
}
size_t MyString::length() const
{
return m_size - 1;
}
const char* MyString::c_str() const
{
char * arr = (char*) malloc(m_size + 1);
int i;
for(i = 0; i < m_size; i++)
{
arr[i] = m_buffer[i];
}
arr[i] = '\0';
return arr;
}
bool MyString::operator== (const MyString & other_myStr) const
{
for(int i = 0; (i < m_size) && (i < other_myStr.size()); i++)
{
if(m_buffer[i] != other_myStr.c_str()[i])
{
return false;
}
}
if(m_size != other_myStr.size())
{
return false;
}
return true;
}
MyString & MyString::operator= (const MyString & other_myStr)
{
buffer_deallocate();
buffer_allocate(other_myStr.size());
for(int i = 0; i < other_myStr.size(); i++)
{
m_buffer[i] = other_myStr.c_str()[i];
}
return *this;
}
MyString MyString::operator+ (const MyString & other_myStr) const
{
int length = this->size() + other_myStr.size();
char * temp = (char*)malloc(length);
int j = 0;
for(int i = 0; i < length; i++)
{
if(i < this->size())
{
temp[i] = m_buffer[i];
}
else
{
temp[i] = other_myStr.c_str()[j];
j++;
}
}
MyString rhs = MyString(temp);
return rhs;
}
char & MyString::operator[] (size_t index)
{
return m_buffer[index];
}
const char & MyString::operator[] (size_t index) const
{
return m_buffer[index];
}
std::ostream & operator<<(std::ostream & os, const MyString & myStr)
{
for(int i = 0; i < myStr.size(); i++)
{
os << myStr[i];
}
os << endl;
}
Like I said, the segmentation fault is happening after the entire program is being executed so my guess is that there is some memory leak issue. I appreciate the help in advance.
And here is the main function:
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include "MyString.h"
using namespace std;
int main(void)
{
MyString dft;
if(dft.size() == 0)
{
cout << "Successful Default c-tor" << endl;
}
MyString param("Successful Parameter c-tor");
MyString copy(dft);
cout << param;
MyString ms_size_length("Size and length test:");
cout << ms_size_length;
cout << "Size of MyString: " << ms_size_length.size() << endl;
cout << "Length of MyString: " << ms_size_length.length() << endl;
MyString ms_toCstring("C-String equivalent successfully obtained!");
cout << ms_toCstring.c_str() << endl;
MyString ms_same1("The same"), ms_same2("The same");
if (ms_same1==ms_same2)
{
cout << "Same success" << endl;
}
MyString ms_different("The same (NOT)");
if (!(ms_same1==ms_different))
{
cout << "Different success" << endl;
}
MyString ms_assign("Before assignment");
ms_assign = MyString("After performing assignment");
MyString ms_append1("The first part");
MyString ms_append2(" and the second");
MyString ms_concat = ms_append1 + ms_append2;
cout << ms_concat;
MyString ms_access("Access successful (NOT)");
ms_access[17] = 0;
cout << ms_access;
}
One problem that I noticed is:
m_size = strlen(str);
buffer_allocate(m_size);
That allocates one less than the number of characters you need. As a consequence, you end up not copying the terminating null character to the object's m_buffer.
I suggest changing the constructor to:
MyString::MyString(const char * str)
{
m_size = strlen(str)+1;
buffer_allocate(m_size);
strcpy(m_buffer, str);
}
PS I did not look for other problems in your code. There may be more, or none.