0

Looking at this cplusplus.com time example, got me thinking more about pointers. The code has no delete (and no new).

Warning: I generally try to avoid pointers as much as possible, so I am definitely not proficient.

I've cut a lot of the code from the example below so as to focus on my question:

/* time example */
#include <stdio.h>      /* printf */
#include <time.h>       /* time_t, struct tm, difftime, time, mktime */

int main ()
{
  time_t timer;
  time(&timer);  /* get current time; same as: timer = time(NULL)  */

  return 0;
}

Should I delete timer at the end of this, or is this just pointing to a system resource? My understanding is that whenever I use new, I should use delete. Is it right to think that as I am not using new, I don't need delete.

This stack question seems to be what I am looking for and explains I don't need delete (which matches the example code on the website) as I am not doing a new; however, I am not sure the functions I am using are not calling a new somewhere (as I find it very hard to read the source). How do I know? Do I need to know?

I really hate working with this old time code and can't wait for the upcoming C++20 chrono update, but this is too far away for my project.

leiyc
  • 903
  • 11
  • 23
David
  • 1,050
  • 1
  • 16
  • 31
  • 1
    Don't delete stack variables IF the object itself is on the stack as the function `epilogue` will free up the working of the function `prolog`. When you called `time` you passed the `address of timer (a.k.a. &timer)`. The `time` function merely took the `address of timer`. Let's just imagine and assume that `time_t` on your architecture was `typedef`'d as an `int`, think of it as just passing a pointer of an `int` to the `time` function, where inside the `time` function, it does something like `*timer_addr = 777`. What else confuses you? – Seoul Aug 13 '18 at 04:01
  • 1
    In your code, you would not do `free(&timer)` in C since that will give undefined behaviour, since `timer` is not created using `malloc()`. Similarly, `delete &timer` will also give undefined behaviour in C++, since `timer` is not created with a `new` expression. – Peter Aug 13 '18 at 06:03
  • So timer is not created, but refers to a system timer that already exists? – David Aug 13 '18 at 06:21
  • 1
    @David: `timer` is created in `main` and is destroyed when `main` returns. – MSalters Aug 13 '18 at 07:38
  • @MSalters If this was created deeper in the program, it wouldn't get freed until the entire thing finishes. Is that correct? Can I free it earlier? – David Aug 14 '18 at 03:27
  • @David: Objects which are local to a function are destroyed exactly when the function returns. `new` and `delete` are a way around that, but this is less often needed than you would think. – MSalters Aug 14 '18 at 08:21
  • @MSalters sorry to keep asking, but this object is not local to the function. It's a pointer meaning it needs to be explicitly deleted to free up memory, does it not? I am assuming this is a system object that exists if you request a reference to it or not, meaning there is not need to delete it. – David Aug 14 '18 at 16:10
  • 1
    @David:You can't tell from a mere pointer whether it needs to be `delete`'d, `free`'d, or whether it just points to an object whose lifetime is managed directly by C++. You have to look back, and match the disposal with the creation. `new/delete`, `malloc/free`, neither/neither. – MSalters Aug 15 '18 at 06:33

2 Answers2

5

Short answer:

No!


Long answer:

You don't have a pointer in your code that is pointing to memory allocated with new, so you are not required to delete anything. And, your reasoning is correct that whenever you allocate something in your code, you are responsible to de-allocate that as well. It is best to use RAII (Resource Acquisition Is Initialization) to manage resources that need to be de-allocated.

For your question regarding the internal allocations by an API, as a programmer you yourself are responsible to go through the API's documentation to figure that out. Some APIs require you to de-allocate the allocated memory in a particular way, which is (ideally) very well documented, and you should follow that.

In C, memory allocated with malloc() must be de-allocated with free().

In C++, memory allocated with new or new[] must be de-allocated with delete or delete[], respectively.

BTW, you ought to use C++11's smart pointers (std::unique_ptr and std::shared_ptr along with std::make_unique and std::make_shared respectively) to enforce RAII in your code whenever possible.

Azeem
  • 11,148
  • 4
  • 27
  • 40
  • You commented on using smart pointers, but in this case we can't do that as we aren't creating the object. Is that correct? We could use a smart pointer if we were 'newing' the object. – David Aug 13 '18 at 17:08
  • 1
    @David: You are correct! In your case, you don't have any `new`. Use smart pointers instead of raw pointers; and, use `std::make_unique` and `std::make_shared` instead of `new`. – Azeem Aug 14 '18 at 03:59
0

You just can delete timer if define it as a pointer like this with new keyword :

time_t *timer = new time_t(50);
// do something with *timer
delete timer;

In bellow case :

{
    time_t timer;
    time(&timer);
}

You just pass timer address with & (reference sign) and time_t timer and it stored in stack. At the end of block it will be delete automatically.