Hello I have a problem with pointer on struct in a stack.
I have a stack of struct:
stack<Somethink*> stack1;
And i want to push and pop array of "Somethink"
void Search(Somethink* array_Somethink, int s, int d,) {
stack1.push(&(array_Somethink[s])); //
while (stack1.size() != 0) {
int i = 0;
array_Somethink[i] = *(stack1.pop()); // this return a error
i++;
}
}
I hope someone can give me a tip, how to properly push and pop from this stack
Thank you :D
void Search(Somethink* array_Somethink, int s, int d,) {
stack1.push(&(array_Somethink[s])); //
while (!stack1.empty()) {
int i = 0;
array_Somethink[i] = *(stack1.top());
stack1.pop();
i++;
}
}
My modified code assumes, you have "owning" pointers to the elements on the stack somewhere else. If that is not the case, you would end with memory leaks here, as the pointers in the stack become dangling objects (leaks).
In order to avoid the potential for memory leaks, here, it might be a good idea if you used std::shared_ptr<Somethink> instead of raw pointers. Then, your stack would become a std::stack< std:shared_ptr<Somethink> >.
For details on std::stack operations empty(),pop(),top(), see std::stack in the usual place.
There, you will find explanations such as this:
std::stack::top
C++ Containers library std::stack
reference top();
const_reference top() const;
Returns reference to the top element in the stack. This is the most recently pushed element. This element will be removed on a call to pop(). Effectively calls c.back().
top will return a pointer to the struct and you are trying to assign it to an instance of the struct. Basically you are trying to assign a pointer to Somethink to a position in an array of Somethink's
Related
I developped a blocking queue class as follow
class Blocking_queue
{
public:
Blocking_queue();
int put(void* elem, size_t elem_size);
int take(void* event);
unsigned int get_size();
private:
typedef struct element
{
void* elem;
size_t elem_size;
struct element* next;
}element_t;
std::mutex m_lock;
std::condition_variable m_condition;
unsigned int m_size;
element_t* m_head;
element_t* m_tail;
};
I want the class to be as generic as possible so I'm using a void pointer which is allocated when the element is added to the queue and freed when removed from it.
int Blocking_queue::take(void* event)
{
element_t* new_head = NULL;
int ret = 0;
// Queue empty
if(nullptr == m_head)
{
// Wait for an element to be added to the queue
std::unique_lock<std::mutex> unique_lock(m_lock);
m_condition.wait(unique_lock);
}
if(nullptr == realloc(event, m_head->elem_size))
{
ret = -1;
}
else
{
// Take element from queue
memcpy(event, m_head->elem, m_head->elem_size);
ret = m_head->elem_size;
new_head = m_head->next;
free(m_head->elem);
free(m_head);
m_head = new_head;
if(nullptr == m_head)
{
m_tail = nullptr;
}
m_size -= 1;
}
return ret;
}
If the queue is empty, take() function waits on m_condition until a new element is added.
A pointer event has to be given to copy element's content before freeing it.
To be sure that the given pointer has the right size to copy element's content I reallocate the pointer with its size.
The problem I have with this is that it doesn't allow to pass a function's locale variable because it's allocated on the stack.
So if I do something like this
void function()
{
unsigned int event = 0;
queue->take(&event);
}
I'll have a invalid old size error on realloc.
So if I pass a null pointer or a heap allocated variable it'll work but if I pass a stack variable address it won't.
Is there a way to allow stack variable address to be passed to take() function ?
Is there a way to allow stack variable address to be passed to take()
function ?
The short answer is no. malloc()/free()/realloc() can only work with heap-allocated memory; they will not work with stack-allocated memory.
As for how you might work around this problem, I think it will require some redesign. My first suggestion is to run as far away as possible from (void *) -- void-pointers are extremely unsafe and difficult to use correctly, because the compiler knows nothing about what they point to, and therefore cannot generate errors when the programmer does something incorrectly; this leads to lots of runtime problems. They are more of a C-language construct, still supported in C++ to provide C compatibility, but C++ has better and safer ways to do the same things.
In particular, if all of the data-elements of your queue are expected to be the same type, then the obvious thing to do would be to make your Blocking_queue class templated with that type as a template-argument; then the user can specify e.g. Blocking_queue<MyFavoriteDataType> and use whatever type he likes, and provide easy-to-use by-value semantics (similar to those provided by e.g. std::vector and friends)
If you want to allow mixing data-elements of different types, then the best thing to do would be the above again, but define a common base-class for the objects, and then you can instantiate a Blocking_queue<std::shared_ptr<TheCommonBaseClass> > object that will accept shared-pointers to any heap-allocated object of any subclass of that base class. (If you really need to pass shared-pointers to stack-allocated objects, you can do that by defining a custom allocator for the shared pointer, but note that doing so opens the door to object-lifetime-mismatch issues, since the stack objects may be destroyed before they are removed from the queue)
My assignment is to implement a stack (array-based) with a given capacity that, when attempting to add another element after the stack is full, will grow by a constant value (I used 100).
The problem here I believe lies in my push() function, which adds 100 element to the stack... probably syntactical but I'm not sure at all why my program won't execute.
template<class Type>
class ArrayStack{
enum {default_cap=100};
private:
Type* S; //array storing elements
int CAP; //capacity of stack
int TOP; //top element of stack
public:
ArrayStack(int defc = default_cap); //constructor with default parameter
~ArrayStack(){} //is "delete [] S;" supposed to go in here? not sure
bool isEmpty() const { return (TOP<0); }//is the stack empty?
int size() const { return (TOP+1); }
const Type& top(){ return S[TOP];} //has exception handling, not displayed
Type pop() {--TOP;} //removes top element
//here's the function that concerns me:
//--------------------------------------------
void push (const Type& e){
if(size() == CAP) {
Type* Snew = new Type[CAP+100];
for(int i = 0; i < CAP; i++){
Snew[i] = S[i];
}
delete [] S;
++CAP;
S = Snew;
}
S[++TOP] = e;
}
//--------------------------------------------
//other functions...
};
//constructor:
template<typename T> ArrayStack<T>::ArrayStack(int d)
: S(new T[d]), CAP(d), TOP(-1){}
It's a bit hard to comment since you've only provided partial code, and haven't demonstrated usage (e.g. with a main() function).
However, an obvious problem [which I notice Roger Rowland has identified in his comment too] with the push() function is that it increases allocated size by 100, but only increments CAP. So it will add 100 elements to the array, but only report ability to use the first one added.
The pop() function also discards the top element, and doesn't return it. If the caller ever tries to use the return value from pop() - and users of a stack type do normally expect to be able to use values they pop - the result will be undefined behaviour.
Your destructor definitely needs to use operator delete, unless you clean up dynamically allocated memory in some other way (and you've shown nothing like that). The whole point of operator new is that memory is NOT released until a corresponding operator delete. It will not be cleaned up magically if you forget to do it, and will present a memory leak for (at least) as long as your program runs.
If you want to do things a bit more safely, use a std::vector instead of a pointer (and avoid using operator new directly).
I am writing a program to implement a stack which works like a real world stack means it topples when the size of a stack reaches threshold and therefore need to create a new stack for inserting that new element.
Below is my program for this:
#include <iostream>
#include<vector>
#include<stack>
using namespace std;
class stack_of_plates
{
vector<stack<int> > stacks;
unsigned int stack_size;
public:
stack_of_plates(unsigned int size=100)
{
stack_size=size;
}
void push(int data)
{
if(stacks.empty())
{
stack<int> *sptr= new stack<int>; //on debugging Segmentation fault at thisline
stacks.push_back(*sptr);
}
vector<stack<int> >::iterator it=stacks.end();
if(it->size()==stack_size)
{
stack<int> *sptr= new stack<int>; //on debugging Segmentation fault at thisline
stacks.push_back(*sptr);
}
it->push(data);
}
void pop()
{
if(stacks.empty())
{
cout<<"\nEmpty Stack";
return ;
}
vector<stack<int> >::iterator it=stacks.end();
if(it->empty())
{
it--;
}
it->pop();
}
int top()
{
if(stacks.empty())
{
cout<<"\nEmpty Stack";
return 0;
}
vector<stack<int> >::iterator it=stacks.end();
if(it->empty())
{
it--;
}
return it->top();
}
};
int main()
{
stack_of_plates ss;
ss.push(1);
ss.push(2);
cout<<ss.top();
return 0;
}
On compiling it gives no error or warning. However program terminates with unusual error.
On debugging its giving segmentation fault error indicating problem in allocating new stack.
Kindly help me how should i change my code while allocating the new stack. Please help me removing this error.
stacks.end(); refers to the (nonexistent) element after the end of the vector. You can't dereference it; doing so will cause undefined behaviour, possibly a segmentation fault.
It's not quite clear what you're doing there, but if you want an iterator for the last element, then either decrement it:
vector<stack<int> >::iterator it=stacks.end(); // points past the end
--it; // points to last element
or use a reverse iterator (in which case, you use ++ rather than -- to move backwards through the sequence):
vector<stack<int> >::reverse_iterator it=stacks.rbegin();
Adding an element to a vector can invalidate it, so the it->push_back(data) at the end of push() is incorrect. You could avoid using an iterator here:
void push() {
if (stacks.empty() || stacks.back().size()==stack_size) {
// See below for explanation of this change
stacks.push_back(stack<int>());
}
stacks.back().push(data);
}
In pop(), you probably want to remove the last stack if it's empty; otherwise, you'll end up with two empty stacks at the end, and your code will erroneously try to pop from one of those. Again, doing that could cause a segmentation fault or other undefined behavoiur. You probably want something like:
void pop() {
if (stacks.empty()) {
cout<<"\nEmpty Stack";
return ;
}
stacks.back().pop();
if (stacks.back().empty()) {
stacks.pop_back();
}
}
And now we've established an invariant that the last stack is never empty, top can be a bit simpler:
int top() {
if (stacks.empty()) {
cout<<"\nEmpty Stack";
return 0;
}
return stacks.back().top();
}
Also, you usually don't want to create objects using new, especially in a case like this where you're putting a copy of the object into the vector and then discarding the pointer, leaking the allocated memory. You can add an empty stack to the vector like this:
stacks.push_back(stack<int>());
Sometimes (but not in this case) you might want to store pointers to allocated objects in a container; in that case, either remember to delete them when they're removed from the container, or store smart pointers such as std::unique_ptr. But in this case, just store objects.
There are many problems with the code, so it is hard to say which one is the direct cause of your problem. You need the clean them up one by one and then retest. If you still have a problem, post your new code here.
Here is the list:
You have a memory leak from your allocation with new. Since you have a vector of stacks, all you need to do is resize the vector and a new stack will be allocated. So
stacks.resize(stacks.size() + 1);
instead of
stack<int> *sptr= new stack<int>;
stacks.push_back(*sptr);
vector<>.end() returns an iterator that point to an element AFTER the last one, which is why #Joachim suggested that you need to decrement the iterator before you use it.
You have a logical error when you check whether to transfer storage to a new stack - after checking is the size of the last stack is the max, and creating a new one, you keep pushing on the old one.
I hope this helps.
std::stack<int> already has the functionality you show in your example, so there is no need for a std::vector< std::stack<int> >. By just pushing and popping to the std::stack<int> you avoid most of the issues your having in your code. There is no reason to limit std::stack<int> to stack_size.
Next to that, when you need the last entry in a container, use back() instead of end().
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Can a local variable's memory be accessed outside its scope?
Is there worrying thing to do a code such (getIDs() returns a pointer):
class Worker{
private:
int workerID;
int departID;
int supervisorID;
public:
Worker()
{
workerID=0;
departID=0;
supervisorID=0;
name="anonymous";
workerAddress="none";
}
void setIDs(int worker, int depart, int supervisor)
{
workerID=worker;
departID=depart;
supervisorID=supervisor;
}
int* getIDs()
{
int id[3];
id[0]=workerID;
id[1]=departID;
id[2]=supervisorID;
return id;
}
};
And then, use it such:
Worker obj;
obj.setIDs(11,22,33);
cout<<(*obj.getIDs())<<endl;
cout<<++(*obj.getIDs())<<endl;
cout<<++(++(*obj.getIDs()))<<endl;
I am wondering about that because the compiler shows:
Warning 1 warning C4172: returning address of local variable or
temporary
Your int id[3] is allocated on a stack and gets destroyed when your int* getIDs() returns.
You're return a pointer to a variable that gets destroyed immediately after getIDs() returns. The pointer then becomes dangling and is practically useless as doing anyting with it is undefined behaviour.
Suppose you defined your class like this:
class Worker{
private:
int IDs[3];
public
// ...
int* getIDs() { return IDs; }
};
This partially solves your problem, as the pointer remains valid as long the Worker object is in scope, but it's still bad practice. Example:
int* ptr;
while (true) {
Worker obj;
obj.setIDs(11,22,33);
ptr = obj.getIDs();
cout << *ptr; // ok, obj is still alive.
break;
} // obj gets destroyed here
cout << *ptr; // NOT ok, dereferencing a dangling pointer
A better way of solving this is to implement your custom operator << for your class. Something like this:
class Worker {
private:
int workerID;
int departID;
int supervisorID;
public:
// ...
friend ostream& operator<<(ostream& out, Worker w);
};
ostream& operator<<(ostream& out, const Worker& w)
{
out << w.workerID << "\n" << w.departID << "\n" << w.supervisorID;
return out;
}
Even if this would work, it wouldn't be good practice to do it this way in c++ unless there is some profound reason why you want pointers to int. Raw c-syle arrays are more difficult to handle than, for instance, std::vectors, so use those, like
std::vector<int> getIDs(){
std::vector<int> id(3);
id[0]=workerID; id[1]=departID; id[2]=supervisorID;
return id;
}
If you're worried about the overhead: this is likely to be optimized away completely by modern compilers.
A local (also caled automatic) variable is destroyed once you leave the function where it is defined. So your pointer will point to this destroyed location, and of course referencing such a location outside the function is incorect and will cause undefined behaviour.
The basic problem here is that when you enter a function call, you get a new frame on your stack (where all your local variables will be kept). Anything that is not dynamically allocated (using new/malloc) in your function will exist in that stack frame, and it gets destroyed when your function returns.
Your function returns a pointer to the start of your 3-element-array which you declared in that stack frame that will go away. So, this is undefined behavior.
While you may get "lucky/unlucky" and still have your data around where the pointer points when you use it, you may also have the opposite happen with this code. Since the space is given up when the stack frame is destroyed, it can be reused - so another part of your code could likely use the memory location where your three elements in that array is stored, which would mean they would have completely different values by the time you dereferenced that pointer.
If you're lucky, your program would just seg-fault/crash so you knew you made a mistake.
Redesign your function to return a structure of 3 ints, a vector, or at the very least (and I don't recommend this), dynamically allocate the array contents with new so it persists after the function call (but you better delete it later or the gremlins will come and get you...).
Edit: My apologies, I completely misread the question. Shouldn't be answering StackOverflow before my coffee.
When you want to return an array, or a pointer rather, there are two routes.
One route: new
int* n = new int[3];
n[0] = 0;
// etc..
return n;
Since n is now a heap object, it is up to YOU to delete it later, if you don't delete it, eventually it will cause memory leaks.
Now, route two is a somewhat easier method I find, but it's kind of riskier. It is where you pass an array in and copy the values in.
void copyIDs(int arr[3] /* or int* arr */)
{
arr[0] = workerID;
/* etc */
}
Now your array is populated, and there was no heap allocation, so no problem.
Edit: Returning a local variable as an address is bad. Why?
Given the function:
int* foo() {
int x = 5;
return &x; // Returns the address (in memory) of x
} // At this point, however, x is popped off the stack, so its address is undefined
// (Garbage)
// So here's our code calling it
int *x = foo(); // points to the garbage memory, might still contain the values we need
// But what if I go ahead and do this?
int bar[100]; // Pushed onto the stack
bool flag = true; // Pushed onto the stack
std::cout << *x << '\n'; // Is this guaranteed to be the value we expect?
Overall, it is too risky. Don't do it.
I'm fairly new to C++ and new to pointers as well. I'm currently working on a stack and was trying to reallocate the memory for the stack as the size of the stack reaches the top however, I'm running into issues. I've already done a lot of research both on Google and stack overflow and have found some information helpful but since I'm so new to stacks and C++ I'm still having issues. I was hoping some bright and intelligent people could at least point me in the right direction.
now... Here's my code.
#include <iostream>
#define STACKMAX 20
using namespace std;
template <class T> class StackTemplated {
private:
int top;
T values[STACKMAX];
public:
StackTemplated();
void push(T i);
T pop(void);
bool empty(void);
};
template <class T> StackTemplated<T>::StackTemplated() {
top = -1;
}
template <class T>void StackTemplated<T>::push(T i) {
if (top == STACKMAX - 1) {
// reallocate top of stack. (this is the area I'm having issues)
char * string1;
string1 = (char *)calloc(STACKMAX, sizeof(char));
if (top == STACKMAX - 1) {
cout << "The stack didn't re-allocate.";
exit(1);
}
} else {
top++;
values[top] = i;
}
}
template <class T> T StackTemplated<T>::pop(void) {
if (top < 0) {
printf("%", "Stack underflow!");
exit(1);
} else {
return values[top--];
}
}
template <class T> bool StackTemplated<T>::empty() {
return (top == -1);
}
Here's a list of a few things I noticed:
STACKMAX is a constant. If you're expanding the stack, how will you keep track of how big it currently is?
The values member is a fixed-size array. You won't be able to change the size of it dynamically without changing how this is declared and allocated.
calloc() allocates a new chunk of memory with the number of bytes you specify. You'll need to somehow copy the existing stack into the new memory block, and free the previous one.
You're allocating only STACKMAX bytes in the call to calloc(). You'll probably want to scale this by sizeof T, in case T is not a char.
There will be a lot of details for you to fix up once you address these major points. Good luck.
The problem is that you don't want to reallocate the top of the stack. Rather, you want to allocate a new array of values which is large enough to hold the new values. Also, since you need to reallocate the array, values should be a pointer.
But how about we forget all this. If we're working in c++, let's use what c++ offers us to make our lives easier. After that's done, then try open things up, if you really feel the need.
One of the things I'm referring to is your use of calloc. Using calloc is a bad idea, particularly when using templates. The problem is that since calloc has no type information, it won't do something as basic as calling a constructor. Constructors are very important in OOP, since they guarantee that an object's invariance when it is created. Instead, use the new[] keyword, like
values = new T[STACKMAX];
This allocates an array of T of STACKMAX length. Of course, as Greg points out, you should reconsider the use of STACKMAX, and use a variable instead. Also, values shouldn't be a static array, but should instead have type T*.
Another thing I was referring to is the fact that you are really trying to implement an array which grows dynamically as needed. In c++, we call such a structure a vector. If you use a vector, your entire code reduces to
#include<iostream>
#include<vector>
using namespace std;
template<class T> class StackTemplated {
private:
std::vector<T> vec;
public:
StackTemplated() { } // the constructor is trivial; in fact, you can leave it out if you want
void push(T i);
T pop(void);
bool empty(void);
};
template<class T>
void StackTemplated<T>::push(T i) {
vec.push_back(i);
}
template<class T>
T StackTemplate<T>::pop(void) {
T top = vec.back();
vec.pop_back();
return top;
}
template<class T>
bool StackTemplate<T>::isEmpty(void) {
return vec.size() == 0;
}
That's all. It's a lot less hairy if you can use an existing data structure to implement the new data structure.
Once you get really comfortable with how a vector works (and there's plenty of explanations / documentation on the web), then try implementing the functionality yourself. Bottom line is, implementing a data structure is a lot easier if you know exactly how it's supposed to behave.
I would declare your values like
T* vaules;
Then use new to create it not calloc. You will need to keep track of the top of the stack and size of it. As Greg says when you grow the stack make sure and copy data over and clean up the old one.