why can i not read a string* object - c++

I know this question's is a bit weird but I'm super new to c++ so i have no idea what should I even ask for but,
I am trying to implement a binary tree and i have this function:
std::string* Tree::getChildren(int node) {
std::string children[2];
for (int i = 0; i < 2; i++) {
children[i] = tree[2 * node + i];
}
return children;
}
which I am trying to output like this:
std::string* k = t.getChildren(1);
cout << k[0]<<","<<k[1] << endl;
but this trows the error:
Exception thrown at 0x6A46F3BE (ucrtbased.dll) in Project1.exe: 0xC0000005: Access violation reading location 0xCCCCCCCC. occurred
What does this mean and what should I do to not have it?

This creates a local array of std::string:
std::string children[2];
When the function returns, that array is destroyed so the pointer you return immediately becomes invalid.
A better version would be to use the wrapper class for plain arrays, std::array:
#include <array>
std::array<std::string,2> Tree::getChildren(int node) {
std::array<std::string,2> children;
for (int i = 0; i < 2; i++) {
children[i] = tree[2 * node + i];
}
return children;
}
And use it:
auto k = t.getChildren(1);
cout << k[0]<<","<<k[1] << endl;

Related

Deleting a dynamically allocated Array of Pairs throwing invalid address error

I have a very curious problem. I have a custom class Set, and a custom class Map (I have to recreate the standard library implementations for a class). In my map class, I create an array of pair<string, Set<string>>. But, when I expand my array of values and re-hash the values, I want to delete my old array. But, Whenever (and wherever in my code...) I try to, I get a Invalid address specified to RtlValidateHeap error. This happens even when the delete call is on the line after my new[] statement.
I have private class variable I call pair<string, Set<string>> *values;. Then in my constructor I do the following.
values = new pair<string, Set<string>>[tableSize];
Then when I got to delete values in a member function it threw the invalid address error. The code is below - I swap newValues, and values, then delete newValues in the reallocate() function. That is where the error is thrown
Node: the map is functioning perfectly. I can hash, store, and recall values without any errors.
Expanded Code:
template<>
class Map<std::string, Set<string>> : public MapInterface<string,Set<string>>{
public:
Map() {
numItems = 0;
tableSize = BonusHashTableSize;
values = new pair<string, Set<string>>[tableSize];
for (int i = 0; i < tableSize; ++i) {
values[i].first = "";
}
};
~Map() {
for (int i = 0; i < tableSize; ++i) {
if (values[i].first != "") {
values[i].second.clear();
}
}
delete[] values;
};
void reallocate() {
tableSize *= 2;
pair<string, Set<string>> *newValues = new pair<string, Set<string>>[tableSize];
for (int i = 0; i < tableSize; ++i) {
newValues[i].first = "";
newValues[i].second = Set<string>();
}
for (int i = 0; i < tableSize / 2; ++i) {
if (values[i].first != "") {
int newIndex = rehash(newValues, values[i].first);
newValues[newIndex].first = values[i].first;
newValues[newIndex].second = values[i].second;
Set<string> test = newValues[newIndex].second;
}
}
std::swap(values, newValues);
delete[] newValues;
//member functions
private:
pair<string, Set<string>> *values;
int tableSize;
int numItems;
};
Remove delete values from constructor. What is the purpose of allocation if you are just going to delete in the next line? And also you are using the deleted memory in the next for loop block.
Since you have deleted it here , it will cause invalid memory access error anywhere else because you are trying to delete already deleted memory location.

Using shared_ptr to access addresses in vector to creat a linked list

Here, I am trying to make an array of nodes, which will also be linked as a linked list. I am purposely making the vector and linked list together, so as to make them contiguous, and when I pop from the vector, I can still refer to the memory.
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
struct node {
int data;
std::shared_ptr<node> next;
};
int main(){
vector<node> myArray;
for (int i = 0; i < 10; ++i) {
myArray.push_back(node());
}
for (int i = 0; i < 10; ++i) {
myArray[i].data = i;
myArray[i].next.reset(&myArray[i+1]);
}
std::shared_ptr<node> nodeList(make_shared<node>());
auto here = nodeList;
for (int i = 0; i < 10; ++i) {
here->next.reset(&myArray[i]); // the error occurs in this line
here = here->next;
}
here = nodeList;
here = here->next;
while (here != nullptr) {
cout << here->data << " with address of : " << &(*here) << endl;
}
return 0;
}
When I run this code, I get an error stating error for object 0x7fb8cbc033d0: pointer being freed was not allocated. Why is this happening? Thank you for your help in advance.
1) The pointer you assigned to myArray[i].next is not allocated by anyone, so it will barf when shared_ptr try to delete it.
2) myArray[i].next.reset(&myArray[i+1]); is dangerous, because the vector could reallocate the memory it uses, and this pointer will be invalid.
3) A linked list node doesn't have to store a pointer, you could store a next_index filed and do myArray[i].next_index = i + 1 or something like that.
4) You could also store shared_ptr in the vector if that's what you want.

Issue accessing free list nodes by memory address in pool allocator

I'm attempting to write a simple pool allocator for allocation and deallocation in c++ as part of a uni course task. We were given a reference to to git-user floooh's oryol engine, https://github.com/floooh/oryol/blob/master/code/Modules/Core/Memory/poolAllocator.h, hence I try to do something similar by splitting the pool into puddles that are allocated when needed. Starting with one and then incrementing as memory demands increase.
Each puddle in my case maintains its own free list of nodes and I fail already in creating the first puddle: I get segmentation fault when I try to access node struct data members. Below is my pool allocator class description along with constructor and function for adding a puddle. I commented in caps lock "SEGMENTATION FAULT" in allocNewPuddle() where it fails, line 10 in that function.
Class description:
template<class T> class memAllocator {
public:
memAllocator();
~memAllocator();
struct Puddle;
struct mNode {
mNode* nextN;
mNode* prevN;
uint puddle;
};
struct Puddle {
mNode* headN_free;
mNode* headN_occ;
};
uint numPuddles;
static const uint nodesInPuddle = 512;
static const uint maxPuddles = 512;
Puddle* puddles[maxPuddles];
uint nodeSize;
uint elemSize;
uint puddleStructSize;
void allocNewPuddle();
void* allocate();
void deallocate(void* obj);
void* findNextFreeNode();
template<typename... ARGS> T* create(ARGS&&... args);
void destroy(T* obj);
};
Constructor:
template<class T>
memAllocator<T>::memAllocator() // creates instance of allocator starting with one puddle allocated
{
this->numPuddles = 0;
this->nodeSize = sizeof(mNode);
this->elemSize = nodeSize + sizeof(T);
this->puddleStructSize = sizeof(Puddle);
allocNewPuddle();
}
Add a new puddle:
template<class T>
void memAllocator<T>::allocNewPuddle() // allocates a new puddle
{
// allocate memory for one puddle
assert(numPuddles < maxPuddles);
Puddle* newPuddle = (Puddle*) malloc(puddleStructSize + nodesInPuddle * elemSize);
// allocate nodes in free list pointed to by puddle struct
newPuddle->headN_free = (mNode*) (newPuddle + puddleStructSize + (nodesInPuddle-1)*elemSize);
for (int i = nodesInPuddle-2; i >= 0; i--) {
mNode* curNode = (mNode*) (newPuddle + puddleStructSize + i*elemSize);
// Fails here when attempting to access mNode struct members
curNode->puddle = numPuddles; // SEGMENTATION FAULT HERE ON FIRST ITERATION
curNode->prevN = nullptr;
curNode->nextN = newPuddle->headN_free;
curNode->nextN->prevN = curNode;
newPuddle->headN_free = curNode;
}
newPuddle->headN_occ = nullptr;
puddles[numPuddles] = newPuddle;
numPuddles++;
}
Here is my main.cc:
#include "memAllocator.h"
#include <iostream>
class Test {
public:
Test();
~Test();
int arr[5];
};
Test::Test() {
for (int i = 0; i < 5; i++) {
this->arr[i] = i;
}
}
Test::~Test() {
std::cout << "destructor called" << std::endl;
}
int main(int argc, char* argv[]) {
memAllocator<Test> memPool = memAllocator<Test> ();
Test* test = memPool.create();
for (int i = 0; i < 5; i++) {
std::cout << test->arr[i] << std::endl;
}
memPool.destroy(test);
for (int i = 0; i < 5; i++) {
std::cout << test->arr[i] << std::endl;
}
}
My guess is that I am doing something horribly naïve with c++ pointers, but from what I know the above should work. If not then I look forward to a good scolding.
Oh, and as you can see I'm not bothering to align memory since it is a small assignment, and as I understand this is not essential for it to work it only makes it faster, but is it possible this can cause wrong memory to be read and written to as more is demanded?
You have incorrect address calculation in line
mNode* curNode = (mNode*) (newPuddle + puddleStructSize + i*elemSize);
newPuddle is Puddle pointer, but you trying to add bytes. Thus you have new address far beyond end of allocated memory buffer. So you must add explicit cast to byte pointer (char, uint8_t etc)
mNode* curNode = (mNode*) ((char*)newPuddle + puddleStructSize + i*elemSize);
You must fix this line too
newPuddle->headN_free = (mNode*) (newPuddle + puddleStructSize + (nodesInPuddle-1)*elemSize);

Vector push_back causing Unhandled exception

Everything is working until the compiler tries to perform the push_back operation.
in the if condition proper values are being returned.
I have declared items as:
vector<int> items; // inside the header file.
//inside the .cpp file
void MsPs::findnSort()
{
for(int i = 1; i<50 ; i++)
{
string temp = static_cast<ostringstream*>( &(ostringstream() << i) )->str(); // TO convert int i to a string temp
if(findSupport(temp) >= MIS[i])
{
items.push_back(i);
}
}
}
the following error pops up:
Unhandled exception at 0x5052ad4a (msvcp100d.dll) in PrefixScan.exe: 0xC0000005: Access violation reading location 0x3d4cccd1.
PS: I have one more function using the push_back operation and there it's working fine.
Can anyone help me with this?
Even this gives the same error:
void MsPs::findnSort()
{
for(int i = 1; i<50 ; i++)
{
items.push_back(i);
}
}
I think the issue is that the ostringstream is destructed when the static cast returns. Thus your pointer is dangling when str() is called. Try this instead:
void MsPs::findnSort()
{
for(int i = 1; i<50 ; i++)
{
ostringstream blah;
string temp = (blah << i).str();
if(findSupport(temp) >= MIS[i])
{
items.push_back(i);
}
}
}

Dynamic Memory Allocation for Dictionary

Hi there I need to Build something like a dictionary and each word according to my code can have 100 meanings, but maybe it has only 5 meanings then I will be allocating 95 extra space for nothing or maybe it has more than 100 meanings then the program will crash, I know the vector class is very easy and could be good use of, but the task is almost building my own vector class, to learn how it works. Thus **meanings and some other stuff remain the same and here is my code, Also I know I am causing memory leakage, how can I delete properly? :
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
class Expression {
char *word_with_several_meanings; // like "bank", "class"
char **meanings; // a pointer to a pointer stores all meanings
int meanings_ctr; // meanings counter
//-----------FUNCTIONS------------------------------------------------
public:
void word( char* = NULL );
void add_meaning(char* = NULL);
char* get_word();
int get_total_number_of_meanings();
char* get_meaning(int meanx = 0);
Expression(int mctr = 0); // CTOR
~Expression(); // DTOR
};
Expression::Expression(int mctr ) {
meanings_ctr = mctr; // Setting the counter to 0
meanings = new char * [100]; // Allocate Space for 100 meanings
}
Expression::~Expression() {
delete [] meanings; // Deleting the memory we allocated
delete [] word_with_several_meanings; // Deleting the memory we allocated
}
void Expression::word( char *p2c )
{
word_with_several_meanings = new char[strlen(p2c)+1];
// copy the string, DEEP copy
strcpy(word_with_several_meanings, p2c);
}
void Expression::add_meaning(char *p2c)
{
//meanings = new char * [meanings_ctr+1];
meanings[meanings_ctr] = new char[strlen(p2c)+1];
strcpy(meanings[meanings_ctr++],p2c);
}
char * Expression::get_meaning( int meanx )
{
return *(meanings+meanx);
}
char * Expression::get_word()
{
return word_with_several_meanings;
}
int Expression::get_total_number_of_meanings()
{
return meanings_ctr;
}
int main(void) {
int i;
Expression expr;
expr.word("bank ");
expr.add_meaning("a place to get money from");
expr.add_meaning("b place to sit");
expr.add_meaning("4 letter word");
expr.add_meaning("Test meaning");
cout << expr.get_word() << endl;
for(int i = 0; i<expr.get_total_number_of_meanings(); i++)
cout << " " << expr.get_meaning(i) << endl;
Expression expr2;
expr2.word("class");
expr2.add_meaning("a school class");
expr2.add_meaning("a classification for a hotel");
expr2.add_meaning("Starts with C");
cout << expr2.get_word() << endl;
for( i = 0; i<expr2.get_total_number_of_meanings(); i++)
cout << " " << expr2.get_meaning(i) << endl;
Expression expr3;
expr3.word("A long test ... ");
char str[] = "Meaning_ ";
for (int kx=0;kx<26;kx++)
{
str[8] = (char) ('A'+kx);
expr3.add_meaning(str);
}
cout << expr3.get_word() << endl;
for(i = 0; i < expr3.get_total_number_of_meanings(); i++)
cout << " " << expr3.get_meaning(i) << endl;
return 0;
}
When you are allocating a multi dimensional array with new then you are allocating it with a loop, e.g.
char **x = new char*[size]
for (int i = 0; i < N; i++) {
x[i] = new int[size];
}
So you also have to delete it in this fashion:
for (int i = 0; i < N; i++) {
delete[] x[i];
}
delete[] x;
Thus when you're having arbitrary sizes of your array you'll have to store them somewhere for using them within the destructor.
delete [] meanings; // Deleting the memory we allocated
won't get rid of your memory allocated, only the pointers themselves.
To free up the actual memory, you will need to iterate through your meanings array, and delete [] each element in it.
Something like:
for (int i = 0; i < meanings_ctr; ++i)
{
delete [] meanings[meanings_ctr];
meanings[meanings_ctr] = NULL;
}
delete [] meanings;
--
For the problem of what to do if you get more than 100 meanings (or in general when your collection is full), the standard technique is to allocate a new array that is double the size (which you can do since it is dynamic), copy your existing collection into that one, and then dispose of your existing one.
I'd use a simple linked list (this is simplified, not complete and untested; also there should be proper getters/setters and stuff):
class Meaning {
char text[20];
Meaning *next;
Meaning(const char *text) : next(0) {
strcpy(this->text, text);
}
}
class Word {
char text[20];
Meaning *first;
Meaning *last;
Word(const char *text) : first(0), last(0) {
strcpy(this->text, text);
}
~Word() {
Meaning *m = first, *n;
while(m) {
n = m->next;
delete m;
m = n;
}
}
void AddMeaning(const char *text) {
if (last) {
last = last->next = new Meaning(text);
}
else {
first = last = new Meaning(text);
}
}
void print() {
printf("%s:\n\t", text);
Meaning *m = first;
while (m) {
printf("%s, ", m->text);
m = m->next;
}
}
}