I know those are basics, but I can't get over with it.
I want to add x times y elements to my array.
When I add 1x100000 elements it's fine.
However, when I try to add 5000x5000 elements, it stops immediately, with many different errors, never bad alloc.
I'd be extremaly gladful if someone can give me a clue about this...
#include <iostream>
#include <numeric>
#include <chrono>
#include <cstdlib>
class Array
{
int *tab; //dynamic array
int cnt; //count
public:
Array();
void clearArray();//deleting table
void test_addValueToArray(int index, int value);
};
Array::Array() : tab(nullptr), cnt(0){;}
void Array::clearArray()
{
if(cnt==0)
return;
delete tab;
cnt=0;
}
void Array::test_addValueToArray(int index, int value)
{
int *NewTab = new int[cnt+1];
for(int i=0;i<index;++i)
NewTab[i]=tab[i];
NewTab[index]=value;
for(int i=index+1;i<cnt+1;++i)
NewTab[i]=tab[i-1];
delete[] tab;
tab=NewTab;
++cnt;
}
Array myArray;
int main()
{
int elements, times;
std::cout<<"How many elements?";
std::cin>>elements;
std::cout<<"How many times?";
std::cin>>times;
auto start = std::chrono::high_resolution_clock::now();
for(int j=0; j<times; ++j)
{
for(int i=0; i<elements ; ++i)
myArray.test_addValueToArray(0,rand()%1000);
myArray.clearArray();
}
auto stop = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> time=stop-start;
std::cout<<"Avarage time:"<<time.count()/times<<"\n";
}
Problem is because of use of delete[] for lots of continious memory deallocation,
plus you have used only delete tab which should be changed to delete[] tab in cleararray so you can use smart pointers.
plus: In your test_addValueToArray() when cnt=0 you are trying to deallocate memory which is not allocated at all and i didn't understand why you are passing 0 as index while calling addValueToArray() i think it should be i at that point.
So once you fix this and use smart pointers it should work else it will show bad_alloc exception after running for some time.
Related
While learning the dynamic object creation in C++ i have encountered a doubt . Here is my code.
And my question is , when the limiting condition in the loop is same as that of the no of objects created it works fine. But what happens when the loop works for more than the size given , it seems printing the values entered , but we have created only 4 objects and changed the condition of loop to more than 4
#include <iostream>
using namespace std;
class item{
int number;
public:
item(){
cout<<"Constructor"<<endl;
}
~item(){
cout<<"Destructor"<<endl;
}
void get_num(int num){
number = num
};
void show_num(){
cout<<"Number is "<<number<<endl;
}
};
const int size=4;
int main() {
item *itemObj = new item[size];
item *d = itemObj; //copy the address of itemObj inorder to access its member functions later
int tempNum;
for (int i = 0; i < size; ++i) {
cout<<"Enter the Number"<<endl;
cin>>tempNum;
itemObj->get_num(tempNum);
itemObj++;
}
//to print the numbers entered
for (int i = 0; i < size; ++i) {
d->show_data();
d++;
cout<<d<<endl;
}
delete itemObj;
return 0;
}
Your code isn't working fine at all. Because you change the value of the pointer that you requested from the new operator. When you call the delete for the itemObj at the last line, it doesn't have its original value.
So, instead of modifying the itemObj, you should modify the copy of it which is the pointer d here. Therefore, the problem isn't about the iteration amount of the loop. It's actually the violation on the heap memory.
Also, if you're creating a dynamic array, you should call delete [] instead of delete.
I am getting error of "Double free or corruption(out)" after I print my output. But this error is only coming for small inputs. For bigger inputs program doesn't throw that error. When I create the multidimensional arrays inside the main and delete them, I do not get the error. I have only posted the part of the code which is relevant to this issue here. Please kindly explain how to resolve the issue.
#include<iostream>
#include<vector>
using namespace std;
class Knapsack{
public:
int noItems, capacity, value, weight;
int *weightArray, *valueArray;
int **ValueMatrix, **BacktrackMatrix;
vector<int> itemsChosen;
~Knapsack();
void getInputs(); // reads in data
void findItems(); // calculates best value of items
void backTrack(int row, int col); // backtracks items selected
void print(); //prints out data
};
Knapsack::~Knapsack()
{
delete[] weightArray;
delete[] valueArray;
for(int i=1;i<=noItems;i++)
{
delete[] ValueMatrix[i];
}
delete[] ValueMatrix;
for(int i=1;i<=noItems;i++)
{
delete[] BacktrackMatrix[i];
}
delete[] BacktrackMatrix;
}
void Knapsack::getInputs()
{
cin>>noItems;
cin>>capacity;
weightArray=new int[noItems];
valueArray=new int[value];
for(int i=1;i<=noItems;i++)
{
cin>>value;
valueArray[i]=value;
}
for(int i=1;i<=noItems;i++)
{
cin>>weight;
weightArray[i]=weight;
}
ValueMatrix=new int*[noItems];
for(int i=1;i<=noItems;i++)
{
ValueMatrix[i]=new int[capacity+1];
}
BacktrackMatrix=new int*[noItems];
for(int i=1;i<=noItems;i++)
{
BacktrackMatrix[i]=new int[capacity+1];
}
}
int main()
{
Knapsack *knap=new Knapsack();
knap->getInputs();
knap->findItems();
knap->print();
delete knap;
return 0;
}
I believe the root of your issue is caused by the allocation of valueArray, and the fact that you are iterating out of bounds.
The line valueArray=new int[value]; initializes valueArray with an array of size value which is an uninitialized variable. Perhaps you meant to use noItems?
Also, as songyuanyao pointed out in the comments, your for loops look like for(int i=1;i<=noItems;i++) which starts the counter at 1 and finishes with the counter at noItems, which is erroneous. In a lot of languages, C++ included, arrays start at index 0 (meaning the first item is array[0], not array[1]) and the last item is one minus the size of the array (so the last item of an array with 5 elements is array[4]).
If you change your for loop to start at 0 and end one element before noItems you should be golden. That would be for(int i = 0; i < noItems; i++ )
What's probably happening with smaller allocations is the different chunks of memory are arranged sequentially in the same area of the memory heap, so when you overrun the buffer with data, you're smashing new's bookkeeping data.
When you have larger allocations, the new memory can't fit as cleanly into the free space of the heap, so the allocator ends up leaving some slack space between the allocations. Thus, a small overrun doesn't destroy heap information.
I am a beginner programmer in school still, and I was assigned this problem:
"Make your own dynamic array template. It should allow creating contiguous arrays (filled with things of the same type) which you can extend without worrying about running out of space.
Do one version using malloc and free.
Do one version using new and delete."
So far this is what I have:
#include <iostream>
#include <sstream>
#include "Array.h"
using namespace std;
int main(){
Array<int> *testArray = new Array<int>(5);
testArray->initArray();
testArray->printArray();
testArray->addData(7);
testArray->printArray();
return 0;
}
And here is the "Array.h" file:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
template<typename T>
class Array{
public:
Array(int size){
size = size;
data = new T[size];
};
Array<T> *addData(T dataToAdd){
Array <T> *tmp = new Array <T> (this->size);
tmp->data = this->data;
Array <T> *newData = new Array<T> (this->size + 1);
for (int i = 0; i < this->size + 1; ++i){
if (i < this->size){
//newData->data[i] = tmp->data[i];
newData->setData(tmp->getData()[i], i);
}
else{
//newData->data[i] = dataToAdd;
newData->setData(dataToAdd, i);
}
}
return newData;
};
void initArray(){
for (int i = 0; i < this->size; ++i){
//this->data[i] = i;
this->setData(i, i);
}
};
void printArray(){
ostringstream oss;
string answer = "";
for (int i = 0; i < this->size; ++i){
oss << this->data[i] + " ";
//cout << this->data[i] << " ";
}
answer = oss.str();
cout << answer << "asdf" << endl;
};
T* getData(){
return this->data;
}
int getSize(){
return this->size;
}
void setData(T data, int index){
this->getData()[index] = data;
}
private:
int size;
T* data;
};
So far what SHOULD happen in my main file is there should be an array of 5 ints, that are initialized to 0,1,2,3,4 from the initArray function.
Then it should print out the array, showing "0 1 2 3 4," add another "7" to it, then print the new array out showing "0 1 2 3 4 7."
For some reason, and I think it has something to do with losing data somehow when going between the two files, the field "data" of my Array class is not being properly changed.
I even hardcoded a test for this in main where I wrote a for loop using the setData function that initializes the Array to "0 1 2 3 4," and then manually printed out these values with another for loop, but the output was only "0 0 0 0 0."
Right now, as the code is, the output is:
asdf
asdf
As it was outputting whitespace before so I added the "asdf"'s to see if my printArray worked at all.
To sum up, why is the data in my private field "data" not being properly stored? I am very new to programming in c++ and any advice would be greatly appreciated. Thank you for your time, and if there is anything you do not understand please ask for clarification and I will do my best.
EDIT: problem solved! Thank you everyone who helped, the issue was with my constructor and how I was calling my functions in main.
One issue is your constructor:
Array(int size){
size = size;
data = new T[size];
};
The way you have it, you're just assigning your size argument to itself, which has no effect. One way to fix it would be to use a different name for the argument:
Array(int size_arg){
size = size_arg;
data = new T[size_arg];
};
However, the preferred way is to use the constructor initializer syntax:
Array(int size) : size(size), data(new T[size]) {};
With the constructor initializer syntax, the compiler knows that you are trying to initialize specific members and doesn't get confused between the argument name and the member name.
I have a recursive function that requires me to create a new array every time the function is called. The function also requires the array that was previously created:
void myFunc(int* prevArray)
{
int newSize;
//do some calculations to find newSize
int* newArray;
newArray = new int[newSize];
//do some calculations to fill newArray
//check some stopping condition
myFunc(newArray);
}
This function leaks memory, but I can't avoid that by adding
delete[] newArray;
since I can only add that after calling the function again. How can I solve this?
You can solve this by making use of dynamic memory allocation.
// allocate initial size
const int INITIAL_SIZE = 5;
int *myArray = malloc(sizeof(int) * INITIAL_SIZE));
int myFunc(int *aArray, int numAllocated) {
int numElements = calculateNewSize();
if (numElements != numAllocated) {
// allocate new size
realloc(aArray, (numElements * sizeof(int));
}
return numElements;
}
Now you can call myFunc like this:
int numElements;
numElements = myFunc(myArray, numElements);
When your done using myFunc don't forget to free the memory
free(myArray);
Try something like
void myFunc(int* prevArray)
{
int newSize;
...newArray = new int[newSize];
myFunc(newArray);
delete[] newArray;
}
or better yet use std::unique_ptr to control the newArray memory. In this way you will follow the rule of thumb regarding dynamic memory - that it should have one owner, responsible for both allocating and freeing it.
You might just use a vector and swap the new result into the final result.
#include <iostream>
#include <vector>
struct X { ~X() { std::cout << "Destruction\n"; } };
void recursive(unsigned n, std::vector<X>& result) {
// Put new_result in a scope for destruction
{
std::vector<X> new_result(1);
// Do something
// The previous result is no longer needed
std::swap(result, new_result);
}
// Next recursion
if(n) {
std::cout << "Call\n";
recursive(--n, result);
}
}
int main() {
std::vector<X> result(1);
std::cout << "Call\n";
recursive(3, result);
return 0;
}
I'm having some issues deallocating arrays of a class I have. Below is the Class, a simplified implementation and my code I have tried to use to close it.
Characters class
#include <cstdlib>
class Character
{
private:
bool human;
int Xposition; // the character's postion on the board.
int Yposition; // the character's postion on the board.
bool alive;
public:
Character(); //This is my constructor
~Character(); //This is my destructor
bool isHuman(); //return whether type 1 aka Human
bool isZombie(); //return whether type 2 aka Zombie
void setHuman(); //set to type 1 or Human
void setZombie(); //set to type 2 or Zombie
void setPos(int xpos, int ypos); //set the board position
int X();
int Y();
bool isAlive(); //checks to see if a Human is still alive and to be displayed
bool Dead(); //kills the character and sets alive to false
int num_moves_allowed; //number of moves allowed.
};
Allocation code:
Character *characters[11];
int human_count = 0;
for(int i=0; i<12; i++)
{
characters[human_count] = new Character();
human_count++;
}
Termination code:
for(i=11;i<=0;i--)
{
if(characters)
{
characters[i]->~Character();
delete characters[i]; characters[i] = NULL;
}
}
if(characters)
{
//ERROR IS HERE
delete [] characters;
}
I have tried a number of different "delete" commands on the array and I keep getting an "Debug Assertion Failed!" window. It says that the dbgdel.cpp from visual studio vctools is the problem place on Line 52.
It also says "Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
Someone please help me I'm sure this is very simple.
I'd suggest you avoid using arrays all together. Use a vector of characters.
Declare your vector as
vector<Character> vCharacters;
then insert objects as
for(int i = 0; i < 100; i++)
vCharacters.push_back(Character());
If you want to store pointers to Character objects then wrap them in a shared_ptr which will take care of deallocating them for you.
vector<shared_ptr<Character>> vCharacters;
for(int i =0; i < 100; i++)
{
shared_ptr<Character> spCharacter(new Character());
vCharacters.push_back(spCharacter);
}
Avoid managing memory yourself when C++ can do it fo ryou
The characters array was allocated on the stack, so you don't have to delete it. However, if you want the array to survive the local scope, create it with something like this:
Character **characters = new Character[11];
then your delete[] line should work fine.
Also note that you don't need to call the destructor of Character explicitly: it is called automatically by delete.
As obelix mentioned, you should use a vector from the Standard Template Library.
However, if you're determined to use a raw array:
const int MAX_CHARACTERS = 11;
Character *characters[MAX_CHARACTERS];
for(int characterCount = 0; characterCount < MAX_CHARACTERS; ++characterCount)
{
characters[characterCount] = new Character();
}
...
if (characters != NULL)
{
for(int i = 0; i < MAX_CHARACTERS; ++i)
{
delete characters[i];
}
}
Paolo Capriotti is correct that characters should be declared with new if you want it to last beyond its scope:
const int MAX_CHARACTERS = 11;
Character **characters = new Character*[MAX_CHARACTERS];
for(int characterCount = 0; characterCount < MAX_CHARACTERS; ++characterCount)
{
characters[characterCount] = new Character();
}
...
if (characters != NULL)
{
for(int i = 0; i < MAX_CHARACTERS; ++i)
{
delete characters[i];
}
delete [] characters;
}
A better solution is the standard vector class:
#include <vector>
...
const int MAX_CHARACTERS = 11;
std::vector<Character> characters;
for (int i = 0; i < MAX_CHARACTERS; ++i)
{
characters.push_back(Character());
}
...
characters.clear();
Notice how much easier the cleanup was? (And in this case, it's optional, since when characters is destroyed it will automatically call the destructor of each item it contains.)
Also:
Character *characters[11];
should be
Character *characters[12];
and
for(i=11;i<=0;i--)
should be
for(i=11;i>=0;i--)
i realize this is a simplified use and all, but why bother with heap access at all?
just using
Character characters[11];
could be just as valid, and safe.
std::vector<> is nice, but if the list is always fixed size, and there's no heap involved in member data, why not?