strange behavior with stl containers and pointers - c++

I don't understand why the following does not work:
queue<int*> q;
int counter = 1;
for (int i = 0; i < 3; i++) {
int a[1] = {counter};
q.push(a);
counter++;
}
while (!q.empty()) {
int *top = q.front();
q.pop();
cout << top[0] << endl;
}
It should print out: 1 2 3, but instead 3 3 3 is printed out. This is because the pointers in the queue are all the same after each run through the loop. Why does that happen?

You are storing pointers to local variables and using those pointers after the local variables they point to have gone out of scope.
In other words: you are invoking Undefined Behavior.
Result: It should not print out "1 2 3". It doesn't have to do anything and is allowed to do whatever it likes. "3 3 3" seems reasonable to me, as it is also allowed to crash.

int a[1] = {counter};
q.push(a);
Not correct. It invokes undefined behvaiour, as a doesn't exist outside the curly braces (the for-loop block). Even if it were well-defined, your code has another problem, all the items in queue is same, as a (the same memory) gets used repeatedly in the loop.
The solution is this:
int *a = new int[1];
a[0] = counter;
q.push(a);
If you do so, then you've to deallocate the memory yourself, of course.
But I'm wondering if every item in queue is just one int,then why not use the following:
queue<int> q;
for (int i = 0; i < 3; i++)
{
q.push(counter);
counter++;
}
Or if you really want array, then why not use std::queue<std::vector<int> > as :
std::queue<std::vector<int> > q;
for (int i = 0; i < 3; i++)
{
std::vector<int> v;
v.push_back(counter);
q.push(v); //dont worry - a copy of the vector is being pushed!
counter++;
}
In this way, you don't have to deal with raw pointers. You don't have to allocate or deallocate memory yourself which in my opinion is a safe approach!

You have undefined behavior, since your declaration of a goes out of scope at the end of the loop where you're pushing it into the queue.
What's probably happening is that the memory location of a gets reused each time through, but there are absolutely no guarantees. You might get a different output next time you run it, or you might get a crash, or demons may fly out of your nostrils.

If you insist on using pointers to integers, the following code does what you want:
#include <queue>
#include <iostream>
int main()
{
std::queue<int*> q;
int counter = 1;
for (int i = 0; i < 3; i++) {
int* a = new int;
*a = counter;
q.push(a);
counter++;
}
while (!q.empty()) {
int *top = q.front();
q.pop();
std::cout << *top << std::endl;
delete top;
}
return 0;
}

Related

Main skipping over function?

I'm attempting to teach myself the basics of algorithms and data structures through a free online course, and as such, I though it'd give it a first shot at merge sort. This isn't really going to be used for anything so it's pretty sloppy, but I seem to be having a problem where main is not calling the MergeSort function.
The output is 00000000, (I assume because array is never assigned anything). When I run the program through gdb the program seems to get to that line, and then completely skip over the function and go directly to the loop that prints the array.
Any thoughts? Am I missing something stupid?
#include <iostream>
using namespace std;
int *MergeSort(int array[], int sizeOf);
int main(){
int numbers[8] = {5, 4, 1, 8, 7, 2, 6, 3};
int *array = MergeSort(numbers, 8);
for (int i = 0; i < 8; i++)
cout << array[i];
return 0;
}
int *MergeSort(int array[], int sizeOf){
int *leftArr = new int[sizeOf/2]; // Build arrays to split in half
int *rightArr = new int[sizeOf/2];
if (sizeOf < 2){ // Base case to end recursion
return array;
}
else{
for (int i = 0; i < (sizeOf/2); i++){ // Left gets first half
leftArr[i] = array[i];
}
int j = (sizeOf/2) - 1; // Set point to start building 2nd
for (int i = sizeOf; i >= (sizeOf/2); i--){
rightArr[j] = array[i]; // Build other half of array
j--;
}
leftArr = MergeSort(leftArr, sizeOf/2); // Call Recursive functions
rightArr = MergeSort(rightArr, sizeOf/2);
}
static int *newArray = new int[sizeOf]; // Sorted array to Build
int k = 0; // Iterators to build sorted func
int m = 0;
int p = 0;
while (p < sizeOf){
if (leftArr[k] < rightArr[m]){ // Left Arr's current value is less
newArray[p] = leftArr[k]; // right arr's current calue
k++;
}
else if (leftArr[k] >= rightArr[m]){
newArray[p] = rightArr[k];
m++;
}
p++;
}
//for (int i = 0; i < 8; i++)
// cout << newArray[i] << endl;
return newArray; // Return address to new array
}
There is a fundamental design issue in your MergeSort():
your algorithm is recursive (that's perfect)
unfortunately it returns newArraywhich is static. This means that all invocations use the same instance of the same static variable (and overwrite the one returned by the recursive call).
You need to solve this by making newArray non static. And at the end of the function, you need to delete[] the arrays returned by recursive calls in order to avoid memory leakage.

C++ Pointers and Dynamic Arrays and Delete Operator

Ok so I am going to lay out two programs. Both are dynamic arrays using pointers and the new operator. But one doesn't seem to like the delete operator.
#include <iostream>
int main()
{
int *p;
p = new int[5];
for (int i = 0; i < 5; i++)
{
p[i] = 25 + (i * 10);
std::cout << p[i] << " ";
}
std::cout << std::endl;
delete [] p;
p = NULL;
return 0;
}
That's the first program. It likes the delete operator just fine. Now the program that dislikes the delete operator:
#include <iostream>
int main()
{
int x;
int *p;
p = new int[5];
*p = 4;
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
x = *p;
p++;
*p = x + 1;
}
std::cout << std::endl;
delete [] p;
p = NULL;
return 0;
}
This program compiles just fine. But during execution, it throws an error - free(): invalid pointer: 0xfdb038 .. or whatever the memory address is for that particular execution. So, the question is:
Why can't the delete operator be used in the second case?
I don't want to have memory leak; I don't want the pointer to be dangling.
If I just say p = NULL;, then p = 0, but I believe the pointer is still dangling?, but I'm not sure. Thanks in advance.
Look at this loop in the second piece of code:
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
x = *p;
p++;
*p = x + 1; // <--- Here
}
Notice that in this line, you write to the memory address currently pointed at by p. Since you always increment p and then write to it, you end up writing off past the end of the region that you allocated for p. (If we imagine pOrig as a pointer to where p initially points, then this writes to pOrig[1], pOrig[2], pOrig[3], pOrig[4], and pOrig[5], and that last write is past the end of the region). This results in undefined behavior, meaning that literally anything can happen. This is Bad News.
Additionally, delete[] assumes that you are passing in a pointer to the very first element of the array that you allocated. Since you've incremented p so many times in that loop, you're trying to delete[] a pointer that wasn't at the base of the allocated array, hence the issue.
To fix this, don't write to p after incrementing it, and store a pointer to the original array allocated with new[] so that you can free that rather than the modified pointer p.
You have to delete the pointer that you got from new. However, in your second code you did p++ which changed the pointer. Therefore you tried to delete a pointer you didn't get from new and delete crashes.
To fix this type of error never use new. Instead use std::vector<int> p;. Since you never need new you cannot forget a delete.
Problem is changing p in p++.
You should always store (to delete) original pointer. Like this:
#include <iostream>
int main()
{
int *original = new int[5];
int *p = original;
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
int x = *p;
p++;
*p = x + 1;
}
std::cout << std::endl;
delete [] original;
return 0;
}

How do pointers work

Here is simple code I'm asking my questions about.
struct Class{
public:
int key;
Class*next;
};
int main(){
Class c;
c.key = 1;
Class* p = &c;
for (int i = 2; i < 5; i++){
Class next;
next.key = i;
p->next = &next;
p = p->next;
}
p = &c;
for (int i = 1; i < 5; i++){
std::cout << p->key;
p = p->next;
}
}
Output I was expecting: 1234
Output I've got: 1444
Can you, please, tell me what is wrong with my code, and what do I have to do to get 1234.
for (int i = 2; i < 5; i++){
Class next;
next.key = 2;
p->next = &next;
p = p->next;
}
The lifetime of the next object ends at the end of each iteration. Since you're assigning the address of this object to p->next, this pointer is left dangling when the iteration ends. In the next iteration, when you attempt to use p, you are invoking undefined behaviour.
Your logic seems correct but as the other commentators pointed out the variables created inside a loop are local to that loop so expire as soon as you are out of the loop. You need a minor modification.
Alternate solution: Just replace your first loop with:
for (int i = 2; i < 5; i++){
p->next = new Class;
p->next->key = i;
p = p->next;
}
This will allocate required memory and create a new entry at each iteration.
Hope that helps!
To explain Chris' comment - accessing a variable outside of its scope is undefined behavior. Your next variable's scope is one iteration of the for loop, once you have reached the closing } for the loop (and i++ has run, I think), it is up to the compiler to deal with deallocating the memory for next, and then reinitializing it next run. Your compiler appears to be making the reasonable decision to keep next in the same piece of memory and run the constructor again on each iteration, which is why your memory access is not throwing segmentation faults (IE, trying to access memory your program hasn't been granted access to). Your compiler could also decide to deallocate next as soon as you exit the for loop, but also doesn't appear to be doing that, which is why you are able to access its memory to print.
Long story short, don't worry too much about figuring out why your program does what it does, instead use heap memory as shown by kvorobiev, which will persist past the end of the for loop's scope. As good practice, you should also delete the memory once you are done wit it.
The problem is that inside this loop
for (int i = 2; i < 5; i++){
Class next;
next.key = 2;
p->next = &next;
p = p->next;
}
for each its iteration you are using the same local variable. Thus for the second iteration of the loop p->next points to the same local object.
So your porgram has undefined behaviour because this local object is not alive after exiting the loop. In general case the memory occupied by the local variable can be overwritten.
It seems that as result you have to nodes. One is c that points to already "died" node next and the died node next that points to itself and keeps the last value that was stored in data member key that is 4.
You should either dynamically allocate each node or use an array of nodes of the list.
Here is a demonstrative program that shows how you could use a simialr approach by means of an array.
#include <iostream>
struct Class
{
public:
int key;
Class *next;
};
int main()
{
const size_t N = 4;
Class c[N];
c[0].key = 1;
Class *p = &c[0];
for ( size_t i = 1; i < N; i++ )
{
c[i].key = i + 1;
p->next = &c[i];
p = p->next;
}
p = &c[0];
for ( int i = 0; i < N; i++ )
{
std::cout << p->key;
p = p->next;
}
std::cout << std::endl;
return 0;
}
The output is
1234

Adding pointers to vector in loop

I am slightly confused about the following code
void foo() {
std::list<A*> list;
for (int i = 0; i < 3; i ++) {
A a = A(i);
list.push_back(&a);
}
for (Iterator it = list.begin(); it != list.end(); it++) {
std::cout << (*it);
}
}
which prints out three times the object a with constructor argument 2, i.e. the last object constructed in the loop.
What am I doing wrong here?
You have a list of dangling pointers.
for (int i = 0; i < 3; i ++) {
A a = A(i);
list(&a);
}
In each iteration, this loop creates an object of type A, which is immediately destroyed when the iteration completes. So the contents of the list are undefined. You would need something like this:
for (int i = 0; i < 3; i ++) {
A* a = new A(i);
list(a);
}
...but don't forget to delete them all in another loop when you're done with the list.
The variable a is local to the first for loop, so it is destroyed at the end of each iteration of the loop. This means that after the loop finishes, all three pointers in list point to objects that no longer exist. Dereferencing those pointers causes undefined behaviour.
If you'd like to worry less about remembering to de-allocate the allocated memory (and have a nicer less error prone code) you should use unique_ptr or shared_ptr (read about them and shoose whichever fits your needs best).
Here is a small example (notice how the elements in the vector get deleted when the vector goes out of scope):
cout<<"Scope begins"<<endl;
{
vector< unique_ptr<A> > v;
for (int i=0; i<5; ++i){
v.push_back(unique_ptr<A>(new A(i)) );
}
}
cout<<"Scope ends"<<endl;
Live demo here.

How to store pointers to statically allocated objects in a vector?

Lets say I wanted to make a vector of objects and another vector of pointers to those objects (I cannot use dynamic memory). The way I would do it is in the following example.
#include <iostream>
#include <vector>
using namespace std;
class Foo {
public:
int bar;
Foo(int x) : bar(x) {
}
};
int main () {
vector<Foo> foos;
vector<Foo*> pFoos;
for (int i = 0; i < 10; i++) {
Foo foo(i);
foos.push_back(foo);
pFoos.push_back(&foos.back());
}
for (int i = 0; i < 10; i++) {
cout << foos[i].bar << endl;
cout << pFoos[i]->bar << endl;
}
}
I think this should work because foos stores a copy of the object, and then I store the reference to the copy (because the original foo will be undefined, so I shouldn't store a reference to that). But this is what I get:
0
36741184
1
0
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
The first to numbers from pFoos are wrong. Furthermore, the large number changes every time. I don't see anything that would cause this undefined behavior. Could someone tell me what I'm doing wrong?
Adding items to a vector invalidates all previous iterators. Calling push_back on the vector may make the pointers you got from it previously invalid if the vector needs to reallocate its internal storage.
If you knew that you were never going to grow the vector again then this would work:
for (int i = 0; i < 10; i++) {
foos.push_back(Foo(i));
}
for (int i = 0; i < 10; i++) {
pFoos.push_back(&foos[i]);
}
or as commented by rodrigo:
foos.reserve(10)
for (int i = 0; i < 10; i++) {
Foo foo(i);
foos.push_back(foo);
pFoos.push_back(&foos.back());
}
for (int i = 0; i < 10; i++) {
cout << foos[i].bar << endl;
cout << pFoos[i]->bar << endl;
}
I guess this is not a good programming approach. The vector is responsible for storing objects and it may REALLOC memory to get bigger memory blobs ... So, your pointer is not valid anymore ...
vector::push_back can move elements, which is why the addresses aren't valid. You can pre-load the memory for the vector to its final size by calling reserve before you start pushing things into the vector, or you can wait until you've finished pushing things before you take their addresses.
But you say that you "cannot use dynamic memory". vector uses dynamic memory.