ESPHome C++ freeing memory

I took a C class in college in the 90s. For various reasons I have used other languages since. I seem to recall variables had to be cleaned up to free them from memory. Is this true of the C++ code we are using?

I created a couple of functions that are included in my Irrigation Controller project. I am aiming to make this thing reliable so our plants and our pool pump don’t die from lack of water. Is there anything I should do differently with the code below? It doesn’t have to be super optimized, I just don’t want memory to leak until the device becomes unresponsive.

#include "esphome.h"
using namespace std;

// Declare functions before calling them.
bool scheduled_runtime(string);
string update_next_runtime(string);

bool scheduled_runtime(string time) {
  // Retrieve the current time.
  auto time_now = id(homeassistant_time).now();
  int time_hour = time_now.hour;
  int time_minute = time_now.minute;

  // Split the hour and minutes.
  int next_hour = atoi(time.substr(0,2).c_str());
  int next_minute = atoi(time.substr(3,2).c_str());

  //ESP_LOGD("scheduled_runtime()", "now: %i:%i", next_hour, next_minute);
  return (time_hour == next_hour && time_minute == next_minute);
}

string update_next_runtime(string time_list) {
  // Initialize variables.
  vector<string> times;
  vector<string> next_time;
  char * token;

  // Split the list of run times into an array.
  token = strtok(&time_list[0], ",");
  while (token != NULL) {
    times.push_back(token);
    token = strtok(NULL, ",");
  }

  // Stop now if the list does not contain more than one time.
  if (times.size() <= 1) {
    return time_list;
  }

  // Retrieve the current time.
  auto time_now = id(homeassistant_time).now();
  int time_hour = time_now.hour;
  int time_minute = time_now.minute;

  // Initialize variables.
  int next_hour = 0;
  int next_minute = 0;
  int index = 0;
  int loop_count = 0;
  int time_count = times.size()-1;

  // Compare the list of times with the current time, and return the next in the list.
  //ESP_LOGD("update_next_runtime", "now: %i:%i", hour, minute);
  for (string time : times) {
    // Retrieve the next scheduled time from the list.
    next_hour = atoi(time.substr(0,2).c_str());
    next_minute = atoi(time.substr(3,2).c_str());

    //ESP_LOGD("update_next_runtime", "next_hour: %s", time.c_str());
    if (time_hour < next_hour || (time_hour == next_hour && time_minute < next_minute)) {
      // Return this time if the next hour is greater than the current hour.
      return times[loop_count].c_str();
      break;
    // When we reach the end of our schedule for the day, return the first time of tomorrow.
    } else if (time_count == loop_count) {
      return times[0].c_str();
      break;
    }

    // Increment the loop counter and array index.
    loop_count += 1;
    index += 2;
  }

  delete token;
  token = NULL;

  return "unknown";
}

as a general rule if you don’t write new, then don’t write delete, the rule of if you allocate it then you deallocate it, applies.

your code looks ok until delete token; and token = NULL is just useless

I understand your worries but a quick search on strtok mem management reveals how it works and thus makes delete actually a possible bug instead of a mem allocation issue.

c++ memory management evolved, now there are stuff like smart pointers and other things so malloc, and even new and delete are being used less.

1 Like

also esphome uses a modern flavor of c++ so std::string is available and sometimes it is more friendlier than c like functions like strtok

Thank you very much Guillermo. I was unsure and my Google-fu left me unclear. You cleared it up for me.

I remember the professor presenting memory management as a big deal and one of the reasons for C. But… I’m not too surprised, it was 20+ years ago at this point. :grin:

It’s still a big deal, but modern c++ (since 11) has smart pointers making the use of new/delete to be considered dirty coding.

Basically whatever is constructed on the stack or in scope, will get destroyed when it goes off the stack or out of scope. If you construct/allocate on heap and store a reference in a smart pointer (std::unique_ptr or std::shared_ptr) then when these smart pointers go away, they’ll deal with whatever you’ve put on the heap.

1 Like