在 C + + 中删除指针

背景: 我正在努力理解指针,我们几周前才在学校看到它们,而今天在练习的时候我碰到了一个傻瓜?问题,它可以是超级直接的,但我几乎没有编程经验。

关于删除指针,我已经看到了很多问题,但它们似乎都与删除一个类有关,而不是一个“简单”指针(或者不管正确的术语是什么) ,下面是我正在尝试运行的代码:

#include <iostream>;


using namespace std;


int main() {
int myVar,
*myPointer;


myVar = 8;
myPointer = &myVar;


cout << "delete-ing pointers " << endl;
cout << "Memory address: " << myPointer << endl;


// Seems I can't *just* delete it, as it triggers an error
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// Error: a.out(14399) malloc: *** error for object 0x7fff61e537f4:
// pointer being freed was not allocated
// *** set a breakpoint in malloc_error_break to debug
// Abort trap: 6


// Using the new keyword befor deleting it works, but
// does it really frees up the space?
myPointer = new int;
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// myPointer continues to store a memory address.


// Using NULL before deleting it, seems to work.
myPointer = NULL;
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// myPointer returns 0.


}

所以我的问题是:

  1. 为什么第一个案子不起作用?使用和删除指针似乎是最直接的用法?这个错误说明没有分配内存,但是‘ cout’返回了一个地址。
  2. 在第二个例子中,错误没有被触发,但是对 myPointer 还是的值进行计数返回了一个内存地址?
  3. 3号真的有用吗?在我看来,指针不再存储地址了,这是删除指针的正确方法吗?

对于这个长长的问题,我很抱歉,希望尽可能地把这个问题说清楚,同时也想重申一下,我没有什么编程经验,所以如果有人能用外行的术语来回答这个问题,我将不胜感激!

377542 次浏览

1 & 2

myVar = 8; //not dynamically allocated. Can't call delete on it.
myPointer = new int; //dynamically allocated, can call delete on it.

The first variable was allocated on the stack. You can call delete only on memory you allocated dynamically (on the heap) using the new operator.

3.

  myPointer = NULL;
delete myPointer;

The above did nothing at all. You didn't free anything, as the pointer pointed at NULL.


The following shouldn't be done:

myPointer = new int;
myPointer = NULL; //leaked memory, no pointer to above int
delete myPointer; //no point at all

You pointed it at NULL, leaving behind leaked memory (the new int you allocated). You should free the memory you were pointing at. There is no way to access that allocated new int anymore, hence memory leak.


The correct way:

myPointer = new int;
delete myPointer; //freed memory
myPointer = NULL; //pointed dangling ptr to NULL

The better way:

If you're using C++, do not use raw pointers. Use smart pointers instead which can handle these things for you with little overhead. C++11 comes with several.

There is a rule in C++, for every new there is a delete.

  1. Why won't the first case work? Seems the most straightforward use to use and delete a pointer? The error says the memory wasn't allocated but 'cout' returned an address.

new is never called. So the address that cout prints is the address of the memory location of myVar, or the value assigned to myPointer in this case. By writing:

myPointer = &myVar;

you say:

myPointer = The address of where the data in myVar is stored

  1. On the second example the error is not being triggered but doing a cout of the value of myPointer still returns a memory address?

It returns an address that points to a memory location that has been deleted. Because first you create the pointer and assign its value to myPointer, second you delete it, third you print it. So unless you assign another value to myPointer, the deleted address will remain.

  1. Does #3 really work? Seems to work to me, the pointer is no longer storing an address, is this the proper way to delete a pointer?

NULL equals 0, you delete 0, so you delete nothing. And it's logic that it prints 0 because you did:

myPointer = NULL;

which equals:

myPointer = 0;
  1. You are trying to delete a variable allocated on the stack. You can not do this
  2. Deleting a pointer does not destruct a pointer actually, just the memory occupied is given back to the OS. You can access it untill the memory is used for another variable, or otherwise manipulated. So it is good practice to set a pointer to NULL (0) after deleting.
  3. Deleting a NULL pointer does not delete anything.

Pointers are similar to normal variables in that you don't need to delete them. They are removed from memory at the end of a functions execution and/or the end of the program.

You can however use pointers to allocate a 'block' of memory, for example like this:

int *some_integers = new int[20000]

This will allocate memory space for 20000 integers. Useful, because the Stack has a limited size and you might want to mess about with a big load of 'ints' without a stack overflow error.

Whenever you call new, you should then 'delete' at the end of your program, because otherwise you will get a memory leak, and some allocated memory space will never be returned for other programs to use. To do this:

delete [] some_integers;

Hope that helps.

int value, *ptr;


value = 8;
ptr = &value;
// ptr points to value, which lives on a stack frame.
// you are not responsible for managing its lifetime.


ptr = new int;
delete ptr;
// yes this is the normal way to manage the lifetime of
// dynamically allocated memory, you new'ed it, you delete it.


ptr = nullptr;
delete ptr;
// this is illogical, essentially you are saying delete nothing.

I believe you're not fully understanding how pointers work.
When you have a pointer pointing to some memory there are three different things you must understand:
- there is "what is pointed" by the pointer (the memory)
- this memory address
- not all pointers need to have their memory deleted: you only need to delete memory that was dynamically allocated (used new operator).

Imagine:

int *ptr = new int;
// ptr has the address of the memory.
// at this point, the actual memory doesn't have anything.
*ptr = 8;
// you're assigning the integer 8 into that memory.
delete ptr;
// you are only deleting the memory.
// at this point the pointer still has the same memory address (as you could
//   notice from your 2nd test) but what inside that memory is gone!

When you did

ptr = NULL;
// you didn't delete the memory
// you're only saying that this pointer is now pointing to "nowhere".
// the memory that was pointed by this pointer is now lost.

C++ allows that you try to delete a pointer that points to null but it doesn't actually do anything, just doesn't give any error.