Stack around the variable ' ' was corrupted in c++ [closed] - c++

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 6 years ago.
Improve this question
I m getting a run-time error when I try to call a constructor , and I think I m not doing right the memory deletion. Here is my construcor :
const int id_ferma;
int suprafata;
int nr_produse;
char* produse[];
Ferma(int id_ferma, int suprafata, int nr_produse, char* produse[]) :id_ferma(id_ferma){
this->suprafata = suprafata;
this->nr_produse = nr_produse;
for (int i = 0; i < nr_produse; i++){
this->produse[i] = new char[strlen(produse[i]) + 1];
strcpy(this->produse[i], produse[i]);
cout << produse[i] << endl;
}
}
And here is my destructor:
~Ferma(){
for (int i = 0; i < nr_produse; i++){
if (this->produse[i] != NULL)
delete produse[i];
}
}
And main:
int main(){
char* produse1[] = { "Lapte oaie", "Branza vaca", "Muschi de porc", "Oua de gaina" };
for (int i = 0; i < 4; i++){
cout << produse1[i];
}
Ferma f1(14, 1500, 4, produse1);
}

You are not allocating any memory for this->produse before trying to populate it. Also, because you are manually managing dynamically allocated memory, you need to implement the Rule of Three manually as well.
Try this instead:
#include <algorithm>
class Ferma
{
private:
int m_id_ferma;
int m_suprafata
int m_nr_produse;
char** m_produse; // <-- change this to char**!
public:
Ferma(int id_ferma, int suprafata, int nr_produse, char* produse[])
: m_id_ferma(id_ferma), m_suprafata(suprafata), m_nr_produse(nr_produse)
{
m_produse = new char*[nr_produse]; // <-- add this!
for (int i = 0; i < nr_produse; ++i)
{
m_produse[i] = new char[strlen(produse[i]) + 1];
strcpy(m_produse[i], produse[i]);
}
}
Ferma(const Ferma &src) // <-- add this!
: m_id_ferma(src.m_id_ferma), m_suprafata(src.m_suprafata), m_nr_produse(src.m_nr_produse)
{
m_produse = new char*[m_nr_produse];
for (int i = 0; i < m_nr_produse; ++i)
{
m_produse[i] = new char[strlen(src.m_produse[i]) + 1];
strcpy(m_produse[i], src.m_produse[i]);
}
}
~Ferma()
{
for (int i = 0; i < m_nr_produse; ++i)
delete[] m_produse[i]; // <-- change this to delete[]!
delete[] m_produse; // <-- add this!
}
Ferma& operator=(const Ferma &rhs) // <-- add this!
{
Ferma tmp(rhs);
std::swap(m_id_ferma, tmp.m_id_ferma);
std::swap(m_suprafata, tmp.m_suprafata);
std::swap(m_nr_produse, tmp.m_nr_produse);
std::swap(m_produse, tmp.m_produse);
return *this;
}
};
That being said, you should stop using manual memory management. Use std::vector and std::string instead, let the STL handle all of the memory management for you:
#include <vector>
#include <string>
class Ferma
{
private:
int m_id_ferma;
int m_suprafata;
std::vector<std::string> m_produse;
public:
Ferma(int id_ferma, int suprafata, int nr_produse, char* produse[])
: id_ferma(id_ferma), m_suprafata(suprafata)
{
m_produse.reserve(nr_produse);
for (int i = 0; i < nr_produse; ++i)
m_produse.push_back(produse[i]);
// alternatively:
// std::copy(produse, produse+nr_produse, std::back_inserter(m_produse));
}
// no destructor, copy constructor, or copy assignment operator needed!
};

You're not initialising the produse field.
If you want to use C++ idiomatically you should use vector instead of raw arrays and string instead of char*.

Since you allocate memory with new[], you need to deallocate it with delete[]:
int *p = new int[10];
...
delete[] p;
int* p[1] = {new int[10]};
...
delete[] p[0];
And since produse is char **, you should allocate memory for produse before trying to dereference it:
char **produse = new char *[10];
produse[0] = new char [10];
...
delete[] produse[0];
delete[] produse;

Related

Array is not resizing with operator new [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 12 months ago.
Improve this question
I want to implement a dynamic array as a class.
I haven written a method which adds an element at the end of the array:
void DynamicArray::addElementAtEnd() {
cout << "\nPodaj liczbe calkowita: ";
int* number = new int;
cin >> *number;
if (DynamicArray::array == NULL) {
DynamicArray::array = new int[1];
DynamicArray::array[0] = *number;
delete number;
(*DynamicArray::size)++;
return;
}
int* buff = new int[*DynamicArray::size + 1];
memcpy(buff, DynamicArray::array, (*DynamicArray::size) * sizeof(int));
delete[] DynamicArray::array;
buff[(*DynamicArray::size)] = *number;
DynamicArray::array = buff;
(*DynamicArray::size)++;
delete number;
return;
};
Here's the .h file of the DynamicArray class:
#include <iostream>
using namespace std;
class DynamicArray {
public:
int* array;
int* size;
public:
DynamicArray() {
DynamicArray::size = new int;
*DynamicArray::size = 0;
};
void handleMenu();
void readFromFile();
void addElementAtEnd();
void addElementAtBeginning();
void addAtIndex(int index);
void deleteElementAtEnd();
void deleteElementAtBeginning();
void deleteElementByIndex(int index);
void showAllElements();
void showElementAtIndex(int index);
void findElementByValue(int value);
};
The problem is that this method adds only the first element, but if I try to add more then nothing happens. I debugged it, and the problem starts on this line:
int* buff = new int[*DynamicArray::size + 1];
I don't know why, but it seems like this line is not creating a bigger array.
I searched for some solutions, and it seems that the problem is connected with using *DynamicArray::size + 1 instead of eg a variable, or I don't do something right with it.
The actual problem is that you are not initializing array to NULL.
So when you check if array is NULL on the first iteration, it is often not.
The minimal solution:
DynamicArray::DynamicArray() {
this->size = 0; // You should use 'size' like an int, not a pointer
this->array = NULL;
}
// Or using the Member Initializer List (by #user4581301)
DynamicArray::DynamicArray(): size(0), array(nullptr) {}
Note: Differences between NULL and nullptr
Other simple solution could be to check if size is equal to 0 instead of checking if array is NULL.
The above change will solve your problem but your code can still be improved.
Take into account the comments of other users.
And make sure to free each dynamically allocated memory.
Let's address a variety of things.
class DynamicArray {
public:
int* array;
int* size;
public:
DynamicArray() {
DynamicArray::size = new int;
*DynamicArray::size = 0;
}
};
A few things here. First, as others have suggested, there's zero reason to make size a pointer.
Next, it's a strong guideline / good idea to always initialize your fields when declared.
So this section of code can look like this:
class DynamicArray {
public:
int* array = nullptr;
int size = 0;
public:
DynamicArray() {
}
};
After that, please use nullptr instead of NULL. NULL is from C, but the correct value in C++ is nullptr.
Now, let's look at this bit of code.
void DynamicArray::addElementAtEnd() {
cout << "\nPodaj liczbe calkowita: ";
int* number = new int;
cin >> *number;
if (DynamicArray::array == NULL) {
DynamicArray::array = new int[1];
DynamicArray::array[0] = *number;
delete number;
(*DynamicArray::size)++;
return;
}
int* buff = new int[*DynamicArray::size + 1];
memcpy(buff, DynamicArray::array, (*DynamicArray::size) * sizeof(int));
delete[] DynamicArray::array;
buff[(*DynamicArray::size)] = *number;
DynamicArray::array = buff;
(*DynamicArray::size)++;
delete number;
return;
};
Aside from the extra colon on the end of the function (entirely not necessary), this is far more complicated than it needs to be. First, get rid of the int pointer. That's just ridiculous.
void DynamicArray::addElementAtEnd() {
cout << "\nPodaj liczbe calkowita: ";
int number = 0;
cin >> number;
int * newArray = new int[size + 1];
newArray[size] = number;
if (array != nullptr) {
for (int index = 0; index < size; ++index) {
newArray[index] = array[index];
}
delete [] array;
}
array = newArray;
++size;
}
A last comment -- it would make far more sense to pass in the new value as an argument to the method, and the calling test code should get the value you're adding. But you're just learning, so this works.
Note also that you shouldn't specify the class the way you have: DynamicArray::array. No one does that. Do it the way I did above.

Creating a personal string vector class

I am not allowed to make use of the vector class so I need to make my own. I made a int vector class and it works fine, but when trying to make it for strings it compiles but gives me an error because of the pointers. Any hint where I am making the mistake? All I did was change every int element for string, but aparently that does not work. Please help I am very confused.
public:
StringRow(){
elements = new string;
size = 0;
}
~StringRow(){...}
void push_back(string value){...}
};
You defined pointer to variable, not array of variables.
elements = new string;
Replace it with
elements = new string[size];
You can optimize algorithm with defining initial size. Create bigger array only if it's necessary.
There are several problems:
in the constructor you don't need to allocate anything. You don't even need a constructor here, you can initialize the members directly as you declare them.
if you allocate with string* tmpElementsArray = new string[size + 1]; you need to deallocate with delete [] tmpElementsArray;
Corrected working version:
#include <string>
#include <iostream>
using namespace std;
class StringRow {
private:
string* elements = nullptr;
int size = 0;
public:
// constructor not needed
// StringRow() {
// elements = nullptr;
// size = 0;
// }
~StringRow() {
delete []elements;
}
void push_back(string value) {
string* tmpElementsArray = new string[size + 1];
for (int i = 0; i<size; i++) {
tmpElementsArray[i] = elements[i];
}
delete [] elements;
elements = tmpElementsArray;
elements[size] = value;
size++;
}
int length() {
return size;
}
string at(int index) {
if (index<size) {
return elements[index];
}
}
};
int main()
{
StringRow s;
string str1 = "hello";
string str2 = "hello2";
s.push_back(str1);
s.push_back(str2);
cout << s.at(0) << endl ;
cout << s.at(1) << endl;
}
Doing a delete []elements if elements is nullptr is OK.
NB: This is not the most efficient way.

Memory leaks from 2d array on heap

I'm having an issue with a lot of memory leaks from a class I've created. The assignment is requires creating a word search puzzle on the heap. I've created my destructor, copy constructor and overload the assignment operator.
I think there must be something wrong with one of these functions, because the final check to ensure it is working is to create objects in a loop, to see if it fails and my function is crashing. I've tried different forms of the destructor and I've tried changing around the copy and assignment operator with no luck. Kind of at a loss, and the lack of warnings is really making it difficult to debug without a proper understanding of the heap.
Any help would be really appreciated!
Here are some functions that are working with the heap.
JumblePuzzle::~JumblePuzzle(){
for (int i = 0; i < size; ++i){
delete jumble[i];
}
delete jumble;
}
JumblePuzzle::JumblePuzzle(string word, string diff){
int i = 0;
toHide = word;
difficulty = diff;
jumble = buildArray();
fillArray();
hideWord();
}
JumblePuzzle::JumblePuzzle(JumblePuzzle& temp){
size = temp.size;
rowPos = temp.rowPos;
colPos = temp.colPos;
direction = temp.direction;
toHide = temp.toHide;
difficulty = temp.difficulty;
jumble = temp.getJumble();
}
JumblePuzzle& JumblePuzzle::operator=(const JumblePuzzle& right){
if (this != &right){
for (int i = 0; i < size; ++i){
delete jumble[i];
}
delete[] jumble;
size = right.size;
rowPos = right.rowPos;
colPos = right.colPos;
direction = right.direction;
toHide = right.toHide;
difficulty = right.difficulty;
jumble = right.getJumble();
}
return *this;
}
charArrayPtr* JumblePuzzle::buildArray() const{
charArrayPtr* array = new char*[size];
for (int i = 0; i < size; ++i){
array[i] = new char[size];
}
return array;
}
Here's the line its failing on.
int loopLimit =20;
for (int i = 0; i < loopLimit; i++)
JumblePuzzle jp("HIDDENWORD", "hard");
Thanks for any possible help!
EDIT:
Here is my .h file as well.
#ifndef JUMBLE_H_
#define JUMBLE_H_
#include <time.h>
#include <cstdlib>
#include <string>
using namespace std;
typedef char* charArrayPtr;
class BadJumbleException {
public:
BadJumbleException(const string&);
string& what();
private:
string message;
};
class JumblePuzzle{
public:
JumblePuzzle(string, string); //simple constructor
JumblePuzzle(JumblePuzzle&); //copy constructor
~JumblePuzzle(); //deconstructor
charArrayPtr* getJumble() const;
JumblePuzzle& operator=(const JumblePuzzle&);
//accessors
int getSize();
int getRowPos();
int getColPos();
char getDirection();
private:
//attributes
int size;
int rowPos;
int colPos;
char direction;
charArrayPtr* jumble;
string toHide;
string difficulty;
void fillArray();
void hideWord();
char randomDirection();
int randomNum(int);
charArrayPtr* buildArray() const;
};
#endif
and my getJumble. It's used to get the actual word search created. Returned a copy rather than the pointer so it cant be modified.
charArrayPtr* JumblePuzzle::getJumble() const{
charArrayPtr* tempJumble = new char*[size];
for (int i = 0; i < size; ++i){
tempJumble[i] = new char[size];
}
for (int i = 0; i < size; i++){
for (int j = 0; j < size; j++){
tempJumble[i][j] = jumble[i][j];
}
}
return tempJumble;
}
There is one major thing wrong with your code, and that is you failed to initialize the "size" member in the JumblePuzzle(string, string) constructor.
There are other things you should do:
1) Create a separate function to destroy the 2d array within the JumblePuzzle class. You seem to be copying the same loops to do this in multiple places. No need for that if you just call a function to do this work.
2) Your assignment and copy constructor are not exception safe. If new[] throws an exception during the creation of the copy, then the original object has invalidated data. In other words, you've destroyed the data, and when you want to create another 2d array, when new[] says "oops", you've destroyed your original data and can't get it back.

I am getting a pointer being free but not allocated error when running make, make test in putty

I am very new to object oriented programming, pointer use and allocating memory in C++. I am working on an assignment for class and initially I had it pass the first three tests listed below by having an array, grade_array, that in the addScore function looked like grade_array[count -1] = grade. Then it would be used in the mean function.
I know this is not the correct way to go about this because I was getting seg faults, so I know I need to have an array, then create a new array (twice the size) that allocates more memory so that I can put the values of the first one into the new one, and then delete to not get memory leaks. The real problem I am having is I do not know if I am even close to correct on the way I am doing this. The error I am getting:
Running cxxtest tests (5 tests)testrunner(85436) malloc: *** error for object 0x107a87970: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
make: *** [test] Abort trap: 6
I have seen a lot of people having similar problems and posting about them on this very site I just cannot seem to fix mine. I saw that it could be that I made a new pointer and tried to them have them point to the same thing so when one deletes the other has nothing to delete or that my initializer is wrong as it doesn't do much. Like I said, very new to the topic so sorry if I have a million questions and so many errors. I have spent a lot of time on this already and was hoping I could maybe get some advice before I waste more time, thanks in advance!
Gradebook.h
#ifndef GRADEBOOK_H
#define GRADEBOOK_H
#include <string>
using namespace std;
class Gradebook {
public:
Gradebook();
Gradebook(const string& filename);
Gradebook(const Gradebook& that);
virtual ~Gradebook();
void initCount();
void addScore(double grade);
double getScoreAt(int i);
int getCount(int i);
string getSourceFile();
double getMean(); // change back to double
double getMin();
double getMax();
double getMedian();
double getStdDev();
int scoresInRange(double low, double high);
private:
string filename;
int* grade_array;
int new_size;
int count;
int count_tracker;
int* grade_point;
};
#endif
Gradebook.cpp
void Gradebook::initCount(){
count = 0;
}
Gradebook::Gradebook() {
}
Gradebook::Gradebook(const string& filename) : filename(filename) {
//this->filename = filename; // i beleive that filename(filename) does this line
//grade_array = new int[this->getCount(0) +1];
}
Gradebook::Gradebook(const Gradebook& that) {
}
Gradebook::~Gradebook() {
for ( int i = 0; i < this->getCount(0); i ++){
delete &grade_array[i];
}
delete grade_array;
}
void Gradebook::addScore(double grade) {
int count_tracker = this->getCount(1); //number of elements in array currently
// grade_array = new int[count_tracker ];
// grade_array = new int[1]; // grade_array is just a *array
grade_array[count_tracker -1 ] = grade; // array[0] is first not array[1]
new_size = count_tracker * 2;
int* new_array = new int[new_size];
for (int i = 0; i < count_tracker ; i++) {
new_array[i] = grade_array[i];
}
delete[] grade_array;
grade_array = new_array;
count_tracker = new_size;
}
double Gradebook::getScoreAt(int i) {
return grade_array[i];
}
int Gradebook::getCount(int i) {
if (i == 1){
count = count + 1;
}
else{
//don't want to add to the actual count
}
return count;
}
string Gradebook::getSourceFile() {
//ifstream foo;
//foo.open(filename);
return filename;
}
double Gradebook::getMean() {
double mean = 0;
count_tracker = this->getCount(0);
for (int i = 0; i < count_tracker ; i++){
//mean = (*(&(grade_array[i])- (bit_count))) + mean;
mean = grade_array[i] + mean;
}
return (mean/count_tracker);
}
GradebookTest.h
#ifndef GRADEBOOK_TEST_H
#define GRADEBOOK_TEST_H
#include <Gradebook.h>
#include <cxxtest/TestSuite.h>
class GradebookTest : public CxxTest::TestSuite {
public:
void testDefaultConstructor(){
string filename = "data1.txt";
Gradebook a(filename);
TS_ASSERT_EQUALS("data1.txt" , a.getSourceFile());
}
void testAddOne() {
Gradebook gb;
gb.initCount();
gb.addScore(110);
TS_ASSERT_EQUALS(120, gb.getScoreAt(1));
TS_ASSERT_DELTA(110, gb.getMean(), 0.001);
TS_ASSERT_EQUALS(4, gb.getCount(0) );
}
void testAddMultiple() {
Gradebook gb;
gb.addScore(75);
TS_ASSERT_EQUALS(1, gb.getCount(0) );
gb.addScore(85);
TS_ASSERT_EQUALS(2, gb.getCount(0));
TS_ASSERT_DELTA(85, gb.getMean(), 0.001);
}
#endif
I think the following is wrong
for ( int i = 0; i < this->getCount(0); i ++){
delete &grade_array[i];
}
You don't need this for loop since you only allocate memory for grad_array. One delete grade_array; is enough.

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;
}
}
}