0

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.

1
  • 2
    Because in the second case you change the p pointer and it doesn't point to the array beginning before the deleting. Commented Jun 18, 2016 at 21:00

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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.

6 Comments

@EdgarRokyan How is that strange? You will notice that you will not find manual memory management in modern C++. There is no need to subject yourself to this error-prone, outdated and unnecessary practice.
@EdgarRokyan There actually is a trend in modern C++ to avoid explicit new and delete operators. Look at, for example, make_shared and make_unique in conjunction with smart pointer types.
@templatetypedef I mean that you can't avoid using explicitly new/delete because of many C libraries, for example, which deal with arrays and raw pointers. So it's much more better to learn how to use new/delete appropriately instead of ignoring them. In such context the phrase "never use new" looks strange for me. Besides the aforementioned advice doesn't answer the question directly.
@EdgarRokyan C doesn't use new or delete, therefore you never need new or delete to work with C libraries. You just use a std::vector and pass pointers to the data to the C library. The first paragraph answers the question directly, the second in a general manner, I don't see how it doesn't.
@templatetypedef What if C library needs a preallocated buffer to fill in? Do you claim that it's better to create a vector and use pointers to it's buffer instead of simply using new and delete?
|
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.