I'm trying to initialize an empty stack of size 3, but my program is not letting me put NULL into even 1 of the elements. I'm not sure what the problem is. The program just stops working when it attempts to initialize one of elements.
Stack300::Stack300 ()
{
for (int i = 0; i < 3; i++)
{
stackArray[i] = '\0';
//stackArray[i] = i;
}
top = 0;
return;
}
My .h file.
#ifndef CONGERA2_H
#define CONGERA2_H
typedef float Element300;
class Stack300
{
public:
Stack300 ();
Stack300 (const int);
Stack300 (Stack300 &old);
~Stack300();
void push300(const Element300);
Element300 pop300();
void viewTB300();
void viewBT300();
private:
const int MAX_STACK = 80;
Element300 * stackArray;
int top;
};
#endif
And my main file.
#include <iostream>
#include "congera2.h"
using namespace std;
int main()
{
Element300 temp1 = 1.1;
Element300 temp2 = 2.2;
Element300 temp3 = 3.3;
Stack300 myStack;
Stack300 myStack2 (myStack);
/* myStack.push300(temp1);
myStack.push300(temp2);
myStack.push300(temp3);*/
cout << "hello";
return 0;
}
In your constructor, you are never allocating any memory to the 'stackArray' member. The following line would accomplish initializing a dynamic array of 3 floating point integers.
stackArray = new float[3];
You will then want to make sure this memory is deallocated in the destructor as well.
Edited to add some useful resources; these pages do a good job explaining the concept behind pointers and dynamic memory allocation:
Pointers,
Dynamic Memory
Related
I am trying to write a simple stack with dynamic memory allocation. Must be with new/delete. Sorry, if it's trivial but I would appreciate if someone could take a look. Any advice is appreciated.
It works, but I want to make peace with valgrind --leak-check=full
stack.cpp
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "stack.h"
#include <algorithm>
#define INITIAL_STACKSIZE 1
stack::stack()
{
top = 0;
size = INITIAL_STACKSIZE;
data = new int[size];
}
stack::~stack()
{
// delete [] ptr; makes it worse "free(): double free detected in tcache 2
// Aborted (core dumped)"
delete [] data;
}
void stack::push(int a)
{
if(top >= size)
{
int new_size = size * 2;
ptr = new int[new_size];
std:: copy(data, data + top, ptr);
data = ptr;
size = new_size;
}
data[top++]=a;
}
int stack::pop()
{
assert(top>0);
return data[--top];
}
stack.h
class stack
{
public:
void push(int a);
int pop();
void clear();
stack();
~stack();
private:
int top;
int size;
int *data;
int *ptr;
};
teststack.cpp
#include <stdio.h>
#include "stack.h"
int main()
{
stack s1;
stack s2;
s1.push(1);
s1.push(2);
s2.push(5);
s2.push(6);
printf("%d %d\n",s1.pop(),s2.pop());
printf("%d\n",s1.pop());
printf("%d\n",s2.pop());
return 0;
}
You need to delete[] data in your stack::push() before you assign ptr to data.
When you assign ptr to data as you do now before freeing the memory stored in data, you lose the pointer to the memory you allocated with new earlier (i.e., you leak memory).
Once you've copied everything out of data with std::copy(), it is safe to free the memory pointed to by data, since the memory has been copied.
So here is what your stack::push() should look like:
void stack::push(int a)
{
if(top >= size)
{
int new_size = size * 2;
ptr = new int[new_size]; // Or if ptr was a local variable,
// this line would be
// int ptr[] = new int[new_size];
std:: copy(data, data + top, ptr);
delete[] data;
data = ptr;
size = new_size;
}
data[top++]=a;
}
I also suggest you remove ptr from being a member variable of the stack class, and instead make it a local variable in the stack::push() method, since it isn't used anywhere else.
I'm attempting to implement an intvector in C++ and am getting a "Segmentation fault: 11" error. I understand this has something to do with memory management, and considering how new I am to C++ it could definitely be a pretty minor mistake. I debugged the code with valgrind and was given messages such as the following:
Use of uninitialized value of size 8, Invalid read of size 4,Conditional jump or move depends on uninitialized value(s).
My best guess is it has something to do with how I'm implementing the arrays. I originally had the arrays stored on the heap but changed it to the stack and still got the same error. I've already implemented an intvector in java, so I was attempting to use similar logic here, which perhaps is part of the issue.
#include <iostream>
#include "IntVector.h"
#include <cmath>
using namespace std;
int num_elements = 0;
int array_size = 0;
int expansion_factor;
void IntVector::expandArray(){
int tempArr[array_size*2];
for(int i =0;i<array_size;i++){
tempArr[i] = array[i];
}
array = tempArr;
array_size = array_size * 2;
}
void IntVector::add(int val){
int tempArr[array_size];
if(array_size == num_elements){
expandArray();
array[num_elements] = val;
}
else{
for(int i = 0;i<array_size;i++){
tempArr[i] = array[i];
}
tempArr[num_elements] = val;
array = tempArr;
}
num_elements++;
}
void IntVector::remove(int index){
}
int IntVector::get(int index) const{
return index;
}
void IntVector::removeLast(){
}
void IntVector::set(int index, int val){
}
std::string IntVector::toString()const {
return "";
}
IntVector::IntVector(int initial_size){
int* array = new int[initial_size];
}
IntVector:: ~IntVector(){
delete[] array;
}
int main(){
IntVector v(0);
v.add(5);
}
#ifndef INTVECTOR_H_
#define INTVECTOR_H_
using std::cout;
class IntVector {
private:
int* array;
int num_elements;
int array_size;
int expansion_factor;
void expandArray();
public:
void add(int val);
void remove(int index);
int get(int index) const;
void removeLast();
void set(int index, int val);
std::string toString() const;
IntVector(int initial_size);
~IntVector();
};
#endif
As mention in the comments, there are definitely some holes in your understanding of C++. Really when dealing with header files you should have a main.cpp, someotherfile.h, someotherfile.cpp. That just best practices to avoid redefinition errors.
There was quite a bit wrong with the way you accessed the private variable. If a class has a private( or even public) variable you don't have to redeclare it each time you want to change its value.
There were one or two major flaws with the way you expanded the vector. If the vector size is initialized to 0 then 0*2 is still 0 so you never actually increased the size. Secondly, when you set the original array = to the new array the new array was just a local array. This means that the memory wasn't actually allocated permanently, once the function ended the temparr was destroyed.
I know this was probably a lot but if you have any question feel free to ask.
main.cpp
#include "IntVector.h"
int main()
{
IntVector v;
IntVector x(10);
v.push(5);
v.push(5);
v.push(5);
v.push(5);
v.push(5);
v.print();
cout << endl;
x.push(5);
x.push(5);
x.push(5);
x.push(5);
x.push(5);
x.print();
return 0;
}
IntVector.h
#include <string>
#include <iostream>
using namespace std;
class IntVector {
private:
int *array;
int num_elements;
int array_size;
//int expansion_factor =; you would only need this if you plan on more than double the vector size
void expandArray(); //normally c++ array double in size each time they expand
public:
//Constructors
IntVector(); //this is a contructor for if nothing is called
IntVector(int initial_size);
//setters
void push(int val); //add
void pop(); //removelast
void remove(int index); //remove
void at(int index, int val); //set
//Getters
int at(int index);
//std::string toString(); I'm changing this to print
void print(); //will print the contents to the terminal
//Deconstructor
~IntVector();
};
IntVector.cpp
#include "IntVector.h"
//constructors
IntVector::IntVector() //no arguments given
{
array = new int[0];
num_elements = 0;
array_size = 0;
}
IntVector::IntVector(int initial_size)
{
array = new int[initial_size];
num_elements = 0;
array_size = initial_size;
}
void IntVector::expandArray()
{
int *tempArr;
if(array_size == 0){
array_size = 1;
tempArr = new int[1];
} else {
//make sure to allocate new memory
//you were creating a local array which was destroy after the function was completed
//using new will allow the array to exist outside the function
tempArr = new int[array_size * 2];
}
for (int i = 0; i < array_size; i++)
{
tempArr[i] = array[i];
}
//make sure to delete the old array otherwise there is a memory leak.
//c++ doesn't have a garbage collector
delete[] array;
array = tempArr;
array_size = array_size * 2;
}
void IntVector::push(int val)
{
num_elements++;
//checking if vector needs to increase
if (array_size <= num_elements)
{
expandArray();
array[num_elements-1] = val;
}
else
{
array[num_elements-1] = val;
}
}
void IntVector::remove(int index)
{
//not sure how to implment this becuase each element has to be a number.
}
int IntVector::at(int index)
{
return array[index];
}
void IntVector::pop()
{
num_elements = num_elements-1; //not really removing it from the "vector" but it won't print out again
}
void IntVector::at(int index, int val)
{
array[index] = val;
}
void IntVector::print()
{
for (int i = 0 ; i < num_elements; i++)
{
cout << array[i] << " ";
}
cout << endl;
}
IntVector::~IntVector()
{
delete[] array;
}
output
5 5 5 5 5
5 5 5 5 5
Hopefully, the comments help. I changed the name of the functions to better match the actual vecter class the already exists in C++. I think it's good to pick apart already defined functions like this because you get a better understanding of how they actually work and not just how to use them.
If you got any questions just leave a comment
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 have a application that is suppose to store graphic elements. I am having an issue where I cant access a variable in a structure. Here is what i have so far.
#include <crtdbg.h>
#include <string.h>
#include <stdio.h>
#include "CLib.h"
enum{ RUNNING = 1 };
struct Point
{
int x, y;
};
struct Line
{
Point start;
Point end;
};
struct GraphicElement
{
enum{ SIZE = 256 };
char name[SIZE];
CStash Lines; // a Stash of Lines
};
struct VectorGraphic
{
CStash Elements; // a Stash of GraphicElements
};
void AddGraphicElement(VectorGraphic*);
void ReportVectorGraphic(VectorGraphic*);
void CleanUpVectorGraphic(VectorGraphic*);
VectorGraphic Image;
int main()
{
char response;
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
// it's a Stash of GraphicElements initialize(&(Image.Elements),sizeof(GraphicElement));
while (RUNNING)
{
printf("\nPlease select an option:\n");
printf("1. Add a Graphic Element\n");
printf("2. List the Graphic Elements\n");
printf("q. Quit\n");
printf("CHOICE: ");
fflush(stdin);
scanf("%c", &response);
switch (response)
{
case '1':AddGraphicElement(&Image); break;
case '2':ReportVectorGraphic(&Image); break;
case 'q':CleanUpVectorGraphic(&Image); return 0;
default:printf("Please enter a valid option\n");
}
printf("\n");
}
return 0;
}
void AddGraphicElement(VectorGraphic* pImage){
int i = 0, counter = 0;
int xPointStart = 0, yPointStart = 0;
int xPointEnd = 0, yPointEnd = 0;
char name[50];
int lineNumber = 0;
GraphicElement *pElement = nullptr;
Line *pLine = nullptr;
initialize(&(Image.Elements), sizeof(GraphicElement));
printf("ADDING A Graphic Element\n");
printf("Please enter the name of the new GraphicElement(<256 characters): ");
fflush(stdin);
scanf("\n%[^\n]s", &name);
fflush(stdin);
strcpy(pElement->name,name);
Anytime I try assigning strcpy(pElement->name,name); it tells me access violation.
The two other files im working with that cannot be changed and are from a textbook called Thinking in C++.
//: C04:CLib.cpp {O}
// Implementation of example C-like library
// Declare structure and functions:
#include "CLib.h"
#include <iostream>
#include <cassert>
using namespace std;
// Quantity of elements to add
// when increasing storage:
const int increment = 100;
void initialize(CStash* s, int sz)
{
s->size = sz;
s->quantity = 0;
s->storage = nullptr;
s->next = 0;
}
int add(CStash* s, const void* element)
{
if (s->next >= s->quantity) //Enough space left?
inflate(s, increment);
// Copy element into storage,
// starting at next empty space:
int startBytes = s->next * s->size;
unsigned char* e = (unsigned char*)element;
for (int i = 0; i < s->size; i++)
s->storage[startBytes + i] = e[i];
s->next++;
return(s->next - 1); // Index number
}
void* fetch(CStash* s, int index)
{
// Check index boundaries:
assert(0 <= index);
if (index >= s->next)
return 0; // To indicate the end
// Produce pointer to desired element:
return &(s->storage[index * s->size]);
}
int count(CStash* s)
{
return s->next; // Elements in CStash
}
void inflate(CStash* s, int increase)
{
assert(increase > 0);
int newQuantity = s->quantity + increase;
int newBytes = newQuantity * s->size;
int oldBytes = s->quantity * s->size;
unsigned char* b = new unsigned char[newBytes];
for (int i = 0; i < oldBytes; i++)
b[i] = s->storage[i]; // Copy old to new
delete[](s->storage); // Old storage
s->storage = b; // Point to new memory
s->quantity = newQuantity;
}
void cleanup(CStash* s)
{
if (s->storage != 0)
{
cout << "freeing storage" << endl;
delete[]s->storage;
}
} ///:~
and the .h file...
//: C04:CLib.h
// Header file for a C-like library
// An array-like entity created at runtime
typedef struct CStashTag {
int size; // Size of each space
int quantity; // Number of storage spaces
int next; // Next empty space
unsigned char* storage;// Dynamically allocated array of bytes
} CStash;
void initialize(CStash* s, int size);
void cleanup(CStash* s);
int add(CStash* s, const void* element);
void* fetch(CStash* s, int index);
int count(CStash* s);
void inflate(CStash* s, int increase);
///:~
GraphicElement *pElement = nullptr;
// ...
strcpy(pElement->name,name);
Somewhere between the top line and bottom line above you need to allocate memory for pElement.
pElement = new GraphicElement();
Also, consider using a std::shared_ptr instead of a raw pointer, given you tagged this C++.
I'm using C++ and am trying to set an array element values with a setter method. The array is a class private member:
class Boo{
private:
int *x;
public:
Boo();
~Boo();
void setX(int,int);
int getX(int);
}
Boo::Boo(){
x = new int[1];
x = 0;
}
void Boo::setX(int value, int index){
//set condition for NULL
x[index] = value;
}
int Boo::getX(int index){
if(x[index] == NULL) {cout<<"invalid index"<<end; return;}
return x[index];
}
void test(){
Boo *p = new Boo();
p->setX(12,0);
cout<<p->getX(0)<<endl;
}
I been trying to test setting the values in 'x' starting with index '0' (like test()) but it crashes. I wanted to write a program where I run a loop counting up, and I set the array values. Can this be accomplish this way?
Do not use new in C++!
In this case, you should use std::vector<int>.
If you want to fix your code unless use std::vector,
#include <cstddef>
#include <iostream>
#include <stdexcept>
#include <memory>
using std::size_t;
class Boo {
private:
int *x;
size_t size;
size_t capacity;
public:
Boo();
~Boo();
void setX(int,size_t);
int getX(size_t);
};
Boo::Boo() : size(), capacity(1) {
this->x = new int[1];
//x = 0;//DO NOT ASSIGN NULL POINTER!!!!
}
Boo::~Boo() noexcept {
delete[] x;
}
void Boo::setX(int value, size_t index){
if(this->capacity <= index) throw std::out_of_range("Boo::setX");//YOU MUST CHECK RANGE
this->x[index] = value;
++this->size;
}
int Boo::getX(size_t index){
if(this->size <= index) throw std::out_of_range("Boo::getX");//YOU MUST CHECK RANGE
return x[index];
}
void test(){
auto p = std::make_unique<Boo>();
p->setX(12,0);
std::cout << p->getX(0) << std::endl;
}
int main(){
test();
}
http://melpon.org/wandbox/permlink/aIhwC5c9o1q8ygIo
Boo::Boo()
{
x = new int[1];
x = 0;
}
you are not able to set value in an array because after initializing with memory, you have set the pointer of an array to null in constructor.
please use x[0] = 0; instead of x = 0;
I have seen a class like this on the internet,
the head file
#ifndef _COMMON_ARRAY_OBJECT_POOL_H_
#define _COMMON_ARRAY_OBJECT_POOL_H_
#include <stdint.h>
namespace easynet
{
class ArrayObjectPool
{
public:
/** construct
* #param elem_size : element size;
* #param elem_num : element number
*/
ArrayObjectPool(uint32_t elem_size, uint32_t elem_num);
~ArrayObjectPool();
uint32_t ElemSize(){return m_ElemSize;}
uint32_t Capacity(){return m_ElemNum;}
bool IsEmpty(){return m_FreeHead==NULL;}
void* Get();
bool Recycle(void *elem);
private:
void *m_Elements;
void *m_End;
void *m_FreeHead;
uint32_t m_ElemSize;
uint32_t m_ElemNum;
};
}
#endif //_COMMON_ARRAY_OBJECT_POOL_H_
the cpp file
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include "ArrayObjectPool.h"
namespace easynet
{
ArrayObjectPool::ArrayObjectPool(uint32_t elem_size, uint32_t elem_num)
{
m_ElemNum = elem_num;
if(elem_size < sizeof(void*))
m_ElemSize = sizeof(void*);
else
m_ElemSize = elem_size;
m_Elements = malloc(m_ElemSize*m_ElemNum);
m_End = (void*)((char*)m_Elements+m_ElemSize*m_ElemNum);
assert(m_Elements != NULL);
//construct list
int i;
void *node = m_Elements;
for(i=0; i<m_ElemNum-1; ++i)
{
*(void**)node = (void*)((char*)node+m_ElemSize);
node = *(void**)node;
}
*(void**)node = NULL;
m_FreeHead = m_Elements; //list head
}
ArrayObjectPool::~ArrayObjectPool()
{
free(m_Elements);
}
void* ArrayObjectPool::Get()
{
if(m_FreeHead == NULL)
return NULL;
void *temp = m_FreeHead;
m_FreeHead = *(void**)m_FreeHead;
return temp;
}
bool ArrayObjectPool::Recycle(void *elem)
{
if(elem<m_Elements || elem>=m_End)
return false;
*(void**)elem = m_FreeHead;
m_FreeHead = elem;
return true;
}
}
The question is I can't understand what does this means:
int i;
void *node = m_Elements;
for(i=0; i<m_ElemNum-1; ++i)
{
*(void**)node = (void*)((char*)node+m_ElemSize);
node = *(void**)node;
}
and what the *(void**) means? thanks!
It's treating the memory as if it were a union between the user's data type, and void*. When the blocks are in the free block list, the void* is used.
You can think of it as:
union ObjectInObjectPool
{
void* ptr_next_free_block;
UserType content;
};
and then that loop is basically doing:
ObjectInObjectPool* node = m_Elements;
for(i=0; i<m_ElemNum-1; ++i) {
node->ptr_next_free_block = node + 1;
node = node->ptr_next_free_block;
}
except that the programmer did by hand all the pointer arithmetic that the compiler's type checker usually does.
A void* is a pointer value that points to untyped memory. When you do *(void**)node = ..., what it is really doing is *node = .... However, with the latter, you are trying to assign something to a void which doesn't make sense with C++'s type system; you have to do as in the former and cast it to a void** so that *node will be a void*, not a void, and you can assign to it.
node = *(void**)node is just node = *node but forcing the type system to work. It just does "assign to node the value of the memory at *node interpreted as a void*".