Should I delete pointers that come from other func

2019-05-31 06:52发布

I have a background in Java and I'm still not fully used to the concept of pointers and scope, so sorry if the question seems silly.

I read somewhere that I should delete pointers that I have allocated on the Heap. I understand that but should I also delete a pointer that is given to me like this:

#include<dirent.h>

DIR* dir;
struct dirent* entries;

dir= opendir("D:/DIR")
entries= readdir(entries)

// Should I delete the pointers after I'm done with them?
delete entries;
delete dir;

Should I delete the pointers which are assigned from somewhere else or just going out of scope deletes them automatically?

Or is it even right to delete them since I haven't assigned them using new? But then if it's wrong how can I make sure that the memory assigned from the other methods would be deleted after I'm finished using them?

4条回答
够拽才男人
2楼-- · 2019-05-31 07:23

Not necessarily.

The unavoidable rule in C++ is that every new needs to be paired with a delete, and every new[] with a delete[], and that malloc, free, &c. are still available.

So it's tempting to suppose that the memory you get back from readdir is required to be released with an explicit call to delete, but that might not be the case:

  1. It might have been allocated with a new[], or even, malloc!

  2. The library might provide a function that you need to call that releases the memory.

  3. If the library has a persuasion to working well with the C++ standard library, it might provide you with a deleter: which you can pass on construction to a smart pointer such as std::unique_ptr.

I think that (2) is most likely and is the most sensible since different C++ runtime environments might perform new and delete differently. (3) is an extension to this concept and if they support it then use that.

The golden rule is to check the documentation and do what it tells you.

查看更多
祖国的老花朵
3楼-- · 2019-05-31 07:24

C is not the same as C++, notably for this aspect.

When using some external C (or C++) function provided by some external library, you should read its documentation and follow the "ownership" rules and conventions. For example if you use getline you understand that you need to free like here. If you use opendir you should use closedir. If you use sqlite3_prepare_v2 you'll need to sqlite3_finalize it, etc... Sometimes you'll think in terms of some abstract data type (like here) with a destructor-like function.

When you develop your own (public or "private") function in C, you need to document if it returns heap allocated memory and who (and how) is responsible of free (or releasing) it.

With C++, you also have smart pointers and RAII; so you generally can avoid manual new and delete. Smart pointers are helpful, but not a silver bullet.

So you should explicit and document conventions (and follow the conventions of external libraries and APIs) about ownership. Understanding and defining wisely such conventions is an important task.

Circular references are difficult to handle (consider weak pointers when applicable). I recommend reading about garbage collection concepts and techniques (e.g. the GC handbook), to at least be able to name appropriately your approaches and understand the limitations and power of reference counting. In some cases, you might even explicitly use a garbage collector library or code your own allocator.

Manual memory management is a whole program property, and that is why it is hard. There are even cases (long-living processes doing a lot of allocation) where you need to be afraid of fragmentation.

Tools like valgrind and the address sanitizer (with GCC's instrumentation options or Clang's ones) are practically very helpful to hunt memory leaks and some other memory bugs. Be also aware of ASLR. Take care to understand the virtual address space of your process. On Linux, read proc(5) then try cat /proc/$$/maps and cat /proc/self/maps in some terminal for a useful insight.

查看更多
做个烂人
4楼-- · 2019-05-31 07:42

Ultimately you should consult the vendor's manual and see if their functions do the cleaning themselves or you need to call another function to do the cleaning etc. In general when talking about raw pointers in C++ you should explicitly release the allocated memory where appropriate. Whether it comes from a function or a new / new[] operator does not make a difference. To avoid this new / delete combination you can utilize smart pointers and the RAII technique.

查看更多
Summer. ? 凉城
5楼-- · 2019-05-31 07:47

There's no definitive answer to the question, because it always depends on the semantics by which the memory was allocated. For example in the very code example you gave, you must not use delete for deallocation, because opendir is not a C++ function (but a POSIX one) and to properly close it you call closedir. The pointer itself then can be discarded (no deletion requierd, closedir internally does the cleanup). Just make sure you don't use it after free (see: use-after-free-bug).

In general you always have to consult the manual of the function that gives you a pointer, where it's also specified exactly how to deallocate it.

Just to give you the idea:

  • malloc/calloc/realloc → free

  • fopen → fclose

  • X… → XFree

查看更多
登录 后发表回答