Будет ли тут утечка памяти

Hadgehogs
Offline
Зарегистрирован: 15.04.2020

День добрый.

В своем скетче я объявляю структуру, которую у меня будут возвращать многие функции:

struct TResult
{
  int ErrorCode;
  String ErrorDescription;
};

К примеру, функция:

TResult SaveSettings()
{
  TResult result = {0, ""};

// разные полезные дела
  return result;
}

И вот так я буду ее вызывать:

    TResult SaveSettingsResult = SaveSettings();
    ReturnResultToHost(&SaveSettingsResult);

где:

void ReturnResultToHost(struct TResult *result)
{
  SendToHost("rsl:КодОшибки=" + String(result->ErrorCode) + "|" + "ОписаниеОшибки=" + result->ErrorDescription);
}

Hadgehogs
Offline
Зарегистрирован: 15.04.2020

Я пришел из Дельфи, где эту структуру я бы разместил в стеке и среда позаботилась бы о ней.

Позаботится ли о ней среда Arduino?

sadman41
Offline
Зарегистрирован: 19.10.2016

Правильней будет - "Позаботится ли о ней компилятор Си". Нет, не позаботится. До тех пор, пока TResult не будет обладать всеми методами копирования содержимого (см. класс String), результат работы SaveSettings() наврядли можно будет назвать предсказуемым. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

у структуры по умолчанию есть конструктор побитного копирования, не надо заботиться, покуда она указатели не хранит.  

Hadgehogs
Offline
Зарегистрирован: 15.04.2020

В структуре есть String. В си это указатель вроде.

Hadgehogs
Offline
Зарегистрирован: 15.04.2020

Вот эта строчка кода

TResult SaveSettingsResult = SaveSettings();

Вызовет ли она создание новой структуры TResult, пустой, в которую потом запишется результат функции?

Если да, что будет с результатом функции? Он освободит свою занятую память?

Что будет дальше со структурой SaveSettingsResult после выхода из основной процедуры?

sadman41
Offline
Зарегистрирован: 19.10.2016

DetSimen пишет:

у структуры по умолчанию есть конструктор побитного копирования, не надо заботиться, покуда она указатели не хранит.  

То есть компилятор без потерь отработает struct someStruct_t someStruct = makeFoolWork(), где struct someStruct_t makeFoolWork() но за счет временного оверхеда по памяти? Мне ООП в МК не особо нужен, так что я не интересовался. Возврат указателей на разные там локально объявленные массивы - потенциально бажный. 

Hadgehogs
Offline
Зарегистрирован: 15.04.2020

Пишу для Arduino DUE, в которой нет замера свободной ОЗУ, но где то валялась UNO, под которую сейчас тесты загоню, проверим.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Hadgehogs пишет:

Пишу для Arduino DUE, в которой нет замера свободной ОЗУ

Всё там есть.

Hadgehogs
Offline
Зарегистрирован: 15.04.2020

Можно увидеть код, который покажет свободный размер ОЗУ?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Hadgehogs пишет:

Можно увидеть код, который покажет свободный размер ОЗУ?

Под Due? Вот:

#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>

int freeRam()
{
	struct mallinfo mi = mallinfo();
	char* heapend = _sbrk(0);
	register char* stack_ptr asm("sp");

	return (stack_ptr - heapend + mi.fordblks);
}

 

Hadgehogs
Offline
Зарегистрирован: 15.04.2020

Проверил, вроде не течет.

Добавил мониторинг памяти в лог

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Hadgehogs пишет:

В структуре есть String. В си это указатель вроде.

А вот те хрен.  Это в Дельфи любой экземпляр класса создается в куче и ты неявно работаешь с указателями, зачастую даже ничего об этом не подозревая.  В Си, все локальные переменные-экземпляры честно создаются как временные, на стеке и при выходе из области видимости (читай, как функция кончится) автоматически вызывается деструктор (ну, если он есть, канеш).  Если ты в своем классе, созданном локально, не хапал память из кучи, ничего не потечет, но члены-указатели могут попортиться, если были. 

rkit
Offline
Зарегистрирован: 23.11.2016

Ардуино программируют на C++, а не C. В C++ есть деструкторы, перегрузка операторов присвоения, и прочее, что решит проблему в данном случае.

GarryC
Offline
Зарегистрирован: 08.08.2016

В С все это давно решили, когда разрешили возвращать нетривиальные типы из функций. Если коротко ответить, то утечки не будет, если долго и действительно интересно - спросите.

rkit
Offline
Зарегистрирован: 23.11.2016

В C вообще нет разделения тривиальный-нетривиальный. Там даже классов нет, к которым относится это разделение.

sadman41
Offline
Зарегистрирован: 19.10.2016

Читал всякое, наткнулся на небольшое исследование, решил поделиться в этой теме:

"Возврат структуры из функции в C++" : https://dev64.wordpress.com/2012/10/11/object-return-in-cpp/

Кратко: возвращается нормально, в ряде случаев без оверхеда.