2D Object Array Memory Issues C++ - c++

When my input looks like this:
11
Harry Kate Fred Carol
My adjacency matrix should put Harry at [7][7], Kate at [7][10], Fred at [7][5], and Carol at [7][2]. However, Carol & Kate get inserted at other locations within the adj. matrix as well. I am guessing this has something to do with stack and heap memory, but I am not sure how to find the bug. Using cout statements, there doesn't appear to be any issues.
Code below
#include <iostream>
#include <string>
#include <stdlib.h>
#include <iostream>
#include <sstream>
using namespace std;
class Element {
public:
string name;
int weight;
string color;
//default constructor
Element(void) {
name = "";
weight = 0;
color = "white";
}
//parameterized constructor
Element(string first) {
name = first;
weight = 0;
color = "white";
}
void setBlack() {
color = "black";
}
};
class AdjMatrix {
public:
int size;
Element ***adj_matrix;
AdjMatrix(void) {
size = 0;
adj_matrix = NULL;
}
AdjMatrix(int n) {
size = n; //sets the size to n
adj_matrix = new Element **[size];
for (int i = 0; i < size; i++) {
adj_matrix[i] = new Element *[i];
}
}
//Destructor class
~AdjMatrix(void) {
delete adj_matrix;
adj_matrix = NULL;
}
//initialize the array with empty elements
void initialize_matrix() {
Element *add_element = new Element("");
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++)
adj_matrix[i][j] = add_element;
}
}
};
int convertToASCII(string letter)
{
int x = letter.at(0);
int index = x - 65;
return index;
};
int main(int argc, char *argv[]) {
string table_size;
cout<<"";
getline(cin,table_size);
int size = atoi(table_size.c_str());
AdjMatrix *myGraph = new AdjMatrix(size);
myGraph->initialize_matrix();
string line;
getline(cin, line);
while (getline(cin,line))
{
if (line.empty())
break;
else {
int x = convertToASCII(line);
stringstream linestream(line);
string temp;
while (linestream >> temp) {
int z = convertToASCII(temp);
myGraph->adj_matrix[x][z] = new Element(temp);
}
}
}
//Print graph
for (int i = 0; i < myGraph->size; i++) {
for (int j = 0; j < myGraph->size; j++)
cout<<"["<<i<<"]["<<j<<"]: "<<myGraph->adj_matrix[i][j]->name<<endl;
}
return 0;
}

Your program has following problem which should be corrected.
//default constructor
Element(void)
Constructor should be defined as
//default constructor
Element()
You should start using the std::vector for your 2D array. This would eliminate the manual memory management. We should avoid to use raw pointer in modern c++. Please refer the following SO post which describes how to use vector for 2D array.
two dimensional array using vector in cpp

In your AdjMatrix(int) ctor, you are constructing your triangular matrix (if that's what you're going for) incorrectly. Try this:
AdjMatrix(int n) {
size = n; //sets the size to n
adj_matrix = new Element **[size];
for (int i = 0; i < size; i++) {
adj_matrix[i] = new Element *[i + 1]; // Or size for a square matrix
}
}

Related

Dynamically allocated two-dimensional array access issue C++

I am having an issue with accessing 2d array elements.
While creating an object I allocate memory for my array in the constructor.
Once the object is created when I try to access array elements I am getting EXC_BAD_ACCESS.
I checked and when still in constructor I can access array elements.
I don’t know what I am doing wrong.
This is my class where I allocate memory for data array;
class TableData
{
public:
TableData(std::string name, int rows, int columns) : tableName(name), rowCount(rows), columnCount(columns)
{
data = new std::string*[rowCount];
for (int count = 0; count < rowCount; ++count)
data[count] = new std::string[columnCount];
columnID.resize(columnCount);
//Below I did a test where can see that I can access array elements
data[0][0]=“test1111”;
std::string test = data[0][0];
}
~TableData()
{
for (int count = 0; count < rowCount; ++count)
delete[] data[count];
delete[] data;
}
std::string **data;
std::string tableName = "";
const int rowCount;
const int columnCount;
std::vector<std::string> columnID;
};
When I try to fill an array with data I am getting "Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)"
ecuData.tables.push_back(TableData(name, tableRowCount, tableColumnCount));
ecuData.tables[i].data[0][0]=“test2222”; // Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
“tables” is a vector of TableData objects
Here is a full function:
void Decoder::getTables(std::fstream &fs, std::vector<char> & buffer, SGBDdata &ecuData)
{
const int ptr_offset = 0x84;
int tableOffset = *reinterpret_cast<int32_t*>(&buffer[0] + ptr_offset);
const int tableCountBufferLength = 4;
vector<char> tableCountBuffer;
fs.seekg(tableOffset, fs.beg);
readAndDecryptBytes(fs, tableCountBuffer, tableCountBufferLength);
int tableCount = *reinterpret_cast<int32_t*>(&tableCountBuffer[0] + 0);
for(int i = 0; i < tableCount; ++i) //iterate through tables
{
int tableBufferLength = 0x50;
vector<char> tableBuffer;
readAndDecryptBytes(fs, tableBuffer, tableBufferLength);
string name(tableBuffer.begin(), tableBuffer.begin() + 0x40);
TrimEnd(name);
int tableColumnOffset = *reinterpret_cast<int32_t*>(&tableBuffer[0] + 0x40);
int tableColumnCount = *reinterpret_cast<int32_t*>(&tableBuffer[0] + 0x48);
int tableRowCount = *reinterpret_cast<int32_t*>(&tableBuffer[0] + 0x4C);
//**This is where I am creating new “TableData” object and putting it into vector<TableData>**
ecuData.tables.push_back(TableData(name, tableRowCount, tableColumnCount));
long savedPos = fs.tellg();
fs.seekg(tableColumnOffset, fs.beg);
//Load column names
for(int j = 0; j < tableColumnCount; ++j)
{
int tableItemBufferLength = 1024;
vector<char> tableItemBuffer;
for(int k = 0; k < tableItemBufferLength; ++k)
{
readAndDecryptBytes(fs, tableItemBuffer, 1);
if (tableItemBuffer[k] == 0)
break;
}
ecuData.tables[i].columnID.push_back(string(tableItemBuffer.begin(), tableItemBuffer.end() - 1));
}
for(int j = 0; j < tableRowCount; ++j)
{
for (int k = 0; k < tableColumnCount; ++k)
{
int tableItemBufferLength = 1024;
vector<char> tableItemBuffer;
for (int l = 0; l < tableItemBufferLength; ++l)
{
readAndDecryptBytes(fs, tableItemBuffer, 1);
if (tableItemBuffer[l] == 0)
break;
}
string s(tableItemBuffer.begin(), tableItemBuffer.end() - 1);
ecuData.tables[i].data[j][k] = s; //**This is where I get my fault**
}
}
fs.seekg(savedPos, fs.beg);
}
}
Here is SGBDdata class. The ecuData object of this class contains a vector data
class SGBDdata
{
public:
std::string sgbdPath;
std::string ecuName;
std::vector<JobData> jobs;
std::vector<TableData> tables;
};
lose all the new, delete, and pointer magic. and use a vector of vectors?
// Example program
#include <iostream>
#include <string>
#include <vector>
class TableData
{
public:
TableData(std::string name, int rows, int columns) : tableName(name), rowCount(rows), columnCount(columns)
{
data.resize(columnCount);
for( int i = 0; i < columnCount; i++)
{
data[i].resize(rowCount);
}
columnID.resize(columnCount);
//Below I did a test where can see that I can access array elements
data[0][0]="test1111";
std::string test = data[0][0];
}
~TableData()
{
}
std::vector<std::vector<std::string>> data;
std::string tableName = "";
const int rowCount;
const int columnCount;
std::vector<std::string> columnID;
};
int main()
{
TableData test = TableData( "me", 3,3);
test.data[0][0]="test2222";
std::cout<<test.data[0][0];
}
I have managed to get the code working. As #dratenik mentioned the problem was related to shallow copy which was taking place in default copy constructor. To get it fixed I have added a move constructor to TableData class.
class TableData
{
public:
TableData(std::string name, int rows, int columns) : tableName(name), rowCount(rows), columnCount(columns)
{
data = new std::string*[rowCount];
for (int count = 0; count < rowCount; ++count)
data[count] = new std::string[columnCount];
columnID.resize(columnCount);
}
TableData(TableData&& t) : rowCount(t.rowCount), columnCount(t.columnCount)
{
tableName=t.tableName;
data = new std::string*[rowCount];
for (int count = 0; count < rowCount; ++count)
data[count] = new std::string[columnCount];
for (int r_count = 0; r_count < rowCount; ++r_count)
for (int c_count = 0; c_count < columnCount; ++c_count)
data[r_count][c_count] = t.data[r_count][c_count];
}
~TableData()
{
for (int count = 0; count < rowCount; ++count)
delete[] data[count];
delete[] data;
}
std::string **data;
std::string tableName = "";
const int rowCount;
const int columnCount;
std::vector<std::string> columnID;
};

accessing to value in two dimensional pointer array in c++

I want to declare two dimensional array with variable size.
I wrote the following code but something goes wrong!
int **p2DArray;
p2DArray = new int*[target_counter_new];
for (int i = 0; i < target_counter_new; ++i)
{
p2DArray[i] = new int[target_counter_old];
}
for(int i_oghli=0;i_oghli<target_counter_new;i_oghli++)
for(int j_oghli=0;j_oghli<target_counter_old;j_oghli++)
{
p2DArray[i_oghli][j_oghli]=i_oghli+10;
cout<<p2DArray[i_oghli][j_oghli];
}
what is problem here ?
#include <iostream>
using namespace std;
const int target_counter_new = 4;
const int target_counter_old = 4;
int main() {
int **p2DArray;
p2DArray = new int*[target_counter_new];
for (int i = 0; i < target_counter_new; ++i) {
p2DArray[i] = new int[target_counter_old];
}
for(int i_oghli=0;i_oghli<target_counter_new;i_oghli++) {
for(int j_oghli=0;j_oghli<target_counter_old;j_oghli++) {
p2DArray[i_oghli][j_oghli]=i_oghli+10;
cout<<p2DArray[i_oghli][j_oghli] << " ";
}
cout << endl;
}
// don't forget to delete the array
for (int i = 0 ; i < target_counter_new; ++i) {
delete [] p2DArray[i];
}
delete [] p2DArray;
return 0;
}
Check here : code
There doesn't appear to be any problem.

Cannot access class member of a 2d array of object pointers (type***)

I am making conway's game of life. I have two classes, one for the plane of cells, and another for the cells. The cells are like a 2d linked list with 4 pointers per cell pointing to the vertical and horizontal neighbors. When trying to access any of the cell pointers to other cells, or the alive member the program crashes.
my code
//game.h
#ifndef GAME_H_
#define GAME_H_
#include <iostream>
class cell{
public:
bool alive;
cell* top;
cell* bot;
cell* lef;
cell* rig;
cell(){
alive = false;
top = bot = lef = rig = nullptr;
}
cell* link(char);
int alive_neighbors();
void link_right(cell*);
void link_down(cell*);
void refresh_cell();
};
class field{
public:
int size;
cell * origin;
bool ** new_state;
cell *** fi;
field(int a);
~field();
};
#endif
and
//game.cpp
#include <iostream>
#include "game.h"
int cell::alive_neighbors(){
int num = 0;
(this->top)?((this->top->alive)?(++num):(num)||((this->top->rig)?((this->top->rig->alive)?(num++):(num)):(num))):(num);
(this->bot)?((this->bot->alive)?(++num):(num)||((this->bot->lef)?((this->bot->lef->alive)?(num++):(num)):(num))):(num);
(this->rig)?((this->rig->alive)?(++num):(num)||((this->rig->bot)?((this->rig->bot->alive)?(num++):(num)):(num))):(num);
(this->lef)?((this->lef->alive)?(++num):(num)||((this->lef->bot)?((this->lef->bot->alive)?(num++):(num)):(num))):(num);
return num;
}
void cell::link_right(cell* linkee){
this->rig = linkee;
linkee->lef = this;
}
void cell::link_down(cell* linkee){
this->bot = linkee;
linkee->top = this;
}
field::field(int a){
size = a;
for (int i= 0; i < size; i++){
fi[i] = new cell*[size];
for (int j = 0; j < size; j++){
fi[i][j] = new cell;
}
}
for (int i = 0; i < size; i++){
for (int j = 0; j < size -1; j++){
this->fi[i][j]->link_right(this->fi[i][j+1]);
this->fi[j][i]->link_down(this->fi[j+1][i]);
}
}
origin = fi[0][0]
}
field::~field(){
for (int i = size -1; i >= 0; i--){
for (int j = size -1;j >= 0; j--){
delete fi[i][j];
}
delete fi[i];
}
}
Error:
#include "game.h"
int main(){
field game(10);
std::cout << game.origin->alive << std::endl; //compiles but crashes :(
std::cout << game.origin->rig << std::endl; //also compiles and crashes without giving adress.
std::cout << game.fi[0][0]->alive; //even directly accessing the cell compiles and crashes.
}
The problem was with game.cpp try this code
//game.cpp
#include <iostream>
#include "stackoverflow.hpp"
int cell::alive_neighbors(){
int num = 0;
(this->top)?((this->top->alive)?(++num):(num)||((this->top->rig)?((this->top->rig->alive)?(num++):(num)):(num))):(num);
(this->bot)?((this->bot->alive)?(++num):(num)||((this->bot->lef)?((this->bot->lef->alive)?(num++):(num)):(num))):(num);
(this->rig)?((this->rig->alive)?(++num):(num)||((this->rig->bot)?((this->rig->bot->alive)?(num++):(num)):(num))):(num);
(this->lef)?((this->lef->alive)?(++num):(num)||((this->lef->bot)?((this->lef->bot->alive)?(num++):(num)):(num))):(num);
return num;
}
void cell::link_right(cell* linkee){
this->rig = linkee;
linkee->lef = this;
}
void cell::link_down(cell* linkee){
this->bot = linkee;
linkee->top = this;
}
field::field(int a){
size = a;
fi = new cell**[size];
for (int i= 0; i < size; i++){
fi[i] = new cell*[size];
for (int j = 0; j < size; j++){
fi[i][j] = new cell;
}
}
for (int i = 0; i < size; i++){
for (int j = 0; j < size -1; j++){
this->fi[i][j]->link_right(this->fi[i][j+1]);
this->fi[j][i]->link_down(this->fi[j+1][i]);
}
}
origin = fi[0][0];
}
field::~field(){
for (int i = size -1; i >= 0; i--){
for (int j = size -1;j >= 0; j--){
delete fi[i][j];
}
delete fi[i];
}
}
I do not understand why people here tend to get annoyed because the ones asking questions are not coding with the "correct" style. We all need to make mistakes and learn from them. On that note in the future when you work on another C++ project. Try using the STL containers, they will be refreshingly simple and efficient. You'll love them.
Also think of n-dimensional arrays this way. Use one * for every dimension. So an int* arr is a 1-D array and an int** arr is a 2-D array. You can switch to a cell** here since you want a 2-D array :)

How to generate dynamic empty 2D array without default constructor in C++

I have a class named Test and I'd like to create empty 2D array that will hold instances of that class and than add them later one by one using constructor that accepts parameters.
Basically, I'd just like to reserve memory that I will fill in later with objects. It needs to bee on a heap since I will have class that will generate 2D arrays of different sizes.
This was my first approach but it doesn't really work since Test class doesn't have default constructor:
Test** arr;
arr = new Test*[10];
for (int i = 0; i < 10; i++)
arr[i] = new Test[10];
[EDIT]
Here is my full test code. All in all, I'm getting wrong values out, it should be numbers from 0 to 99:
#include <iostream>
using namespace std;
class Test {
private:
short number;
public:
Test(short n) {
this->number = n;
}
short getNumber() {
return number;
}
};
int main() {
Test** arr;
arr = new Test*[10*10];
for (int i = 0; i < 100; i++)
arr[i] = new Test(i);
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++)
cout << arr[i][j].getNumber() << " ";
cout << endl;
}
}
Maybe try using a default constructor with default parameters?
Test(int i = 0) {. . .}

c++ reading txt file and store it in a matrix char by char

I need to read a txt file and store it into a matrix (we suppose that it'a a 2x2 matrix). I have a problem with the code below (I semplified it to be more cleat):
#include<stdexcept>
#include<string>
#include<fstream>
using namespace std;
class A{
private:
int **m;
void allocate_mem(int ***ptr){
*ptr = new int *[2];
(*ptr)[0] = new int[2*2];
for(unsigned i = 1; i < 2; i++)
(*ptr)[i] = (*ptr)[0] + i*2;
}
void read_file(string file_input){
ifstream fin(file_input.c_str());
allocate_mem(&m);
char a;
for(unsigned i = 0; i < 2; i++) {
for (unsigned j = 0; j < 2; j++) {
a = fin.get();
if(a=="X"){
//ISO C++ forbids comparison between pointer and integer [-fpermissive]
m[i][j] = 1;
}else{
m[i][j] = 0;
}
}
}
fin.close();
}
public:
A(){
throw logic_error("Error!");
}
A(string file_name){
read_file(file_name);
}
~A(){
delete[] m[0];
delete[] m;
}
};
input.txt
XX
X
I want to store a 2x2 matrix whose elemets are:
11
01
The solution is simple: Write C++ instead of C
Use standard containers instead of manual memory management.
Also, if you know the size of the data at compile-time, why do you use dynamic memory?
int m[2][2];
void read_file(const std::string& file_input) {
ifstream fin(file_input.c_str());
char a;
if( !fin ) throw;
for (std::size_t i = 0; i < 2; i++) {
for (std::size_t j = 0; j < 2; j++) {
a = fin.get();
if (a == 'X') { // '' is for characters, "" for strings. Thats why the compiler
m[i][j] = 1;// warns you (You are comparing the char[], which is decayed to
} else { // char*, with the integer value of the char variable)
m[i][j] = 0;
}
}
}
//Close not needed (RAII)
}