Массив динамических объектов (динамический массив объектов)))

gonzales
Offline
Зарегистрирован: 13.07.2015

Доброго времени суток!

Комрады, направьте на путь истинный, как правильно описать динамический массив.

Я сделал так:

Есть структура

struct TRule {
  byte SceneID;
  byte ElseSceneID;
};

Задаю массив

TRule* Rule[MAX_RULES];

Когда необходимо создаю элемент в массиве

    Rule[RuleID] = new TRule;
    Rule[RuleID]->SceneID = JRule["ExecuteScene"];
    Rule[RuleID]->ElseSceneID = JRule["ElseScene"];

Когда элемент больше не нужен убиваю его

delete Rule[Index];

Вроде все законно, но есть проблема, после 2-3 итерации одного и того же элемента массива в пямять на его место записываются другие данные и МК виснет.

Выяснил это опытным путем, выводя в монитор при создании элемента массива Rule[RuleID]->SceneID. В какой-то момент он перестает быть нулем и я получаю то, что получаю.

Вопрос собственно один, правильно ли я создаю динамический массив? Делал сам по аналогии с теми примерами, что нашел в инете, но там речь шла про отдельные элементы, а не про массив. (http://mypractic.ru/urok-15-ukazateli-v-c-dlya-arduino-preobrazovanie-ra...)

Клапауций 298
Клапауций 298 аватар
Offline
Зарегистрирован: 25.01.2018

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

http://www.cyberforum.ru/cpp-builder/thread780240.html

Logik
Offline
Зарегистрирован: 05.08.2014

gonzales пишет:

Вопрос собственно один, правильно ли я создаю динамический массив?

А почитать доку/книгу? Выделили память для элемента через new - освободили через delete, а для массива еще и [] в обоих случаях. Для delete внутрь []  кол-во не указываем.

b707
Offline
Зарегистрирован: 26.05.2017

gonzales, элементы JRule, на которые ваш массив ссылается - не забываете чистить перед delete7

gonzales
Offline
Зарегистрирован: 13.07.2015

да, спасибо! 

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

Если не трудно, прокомментируйте, как изящнее решить следующую задачу.

На SD-карте хранится инфа об объекте в структурированных txt файлах. Я не знаю заранее, сколько объектов в определенный момент времени будет одновременно использоваться, есть только ограничение сверху (заведомо большое). Выделять память под все объекты - пустая трата ресурсов, потому как реально объектов может быть 3 или 5. При этом я должен иметь возможность обратиться к каждому из элементов. Я для удобстра использовал структуру и (видимо наивно) полагал, что динамический массив позволит мне выделять память под конкретный объект и затем ее освободить. Но походу delete затирает весь массив, а не отдельный элемент. Как быть в такой ситуации?

gonzales
Offline
Зарегистрирован: 13.07.2015

Logik пишет:

gonzales пишет:

Вопрос собственно один, правильно ли я создаю динамический массив?

А почитать доку/книгу? Выделили память для элемента через new - освободили через delete, а для массива еще и [] в обоих случаях. Для delete внутрь []  кол-во не указываем.

Не понятно написали, new, delete - сдесь все понятно, а что подразумевается под "а для массива еще и [] в обоих случаях. Для delete внутрь []  кол-во не указываем"???

 

gonzales
Offline
Зарегистрирован: 13.07.2015

b707 пишет:

gonzales, элементы JRule, на которые ваш массив ссылается - не забываете чистить перед delete7

Они вычищаются сразу после создания элемента

Клапауций 298
Клапауций 298 аватар
Offline
Зарегистрирован: 25.01.2018

gonzales пишет:

Не понятно написали, new, delete - сдесь все понятно, а что подразумевается под "а для массива еще и [] в обоих случаях. Для delete внутрь []  кол-во не указываем"???

просто сделай, как по ссылке, что я дал - нет смысла перечислять бока, что ты напорол.

b707
Offline
Зарегистрирован: 26.05.2017

gonzales пишет:

На SD-карте хранится инфа об объекте в структурированных txt файлах. Я не знаю заранее, сколько объектов в определенный момент времени будет одновременно использоваться, есть только ограничение сверху (заведомо большое). Выделять память под все объекты - пустая трата ресурсов, потому как реально объектов может быть 3 или 5. При этом я должен иметь возможность обратиться к каждому из элементов. Я для удобстра использовал структуру и (видимо наивно) полагал, что динамический массив позволит мне выделять память под конкретный объект и затем ее освободить. Но походу delete затирает весь массив, а не отдельный элемент. Как быть в такой ситуации?

Да вы почти все сделали правильно, вам только массив обьектов нужно отделить от самих обьектов.

1. Описать структуру или класс для обьектов.

2. При появлении нового обьекта - память под каждый обьект выделять динамически.

3. В массиве хранить только ссылку на обьект. Массив можно сделать статическим, ибо даже 10-20 ссылок - это совсем немного байт.

4. Когда нужда в обьекте отпадает - чистите сам обьект, удаляете ссылку на него из массива (заменяете на NULL) и удаляете обьект

 

b707
Offline
Зарегистрирован: 26.05.2017

gonzales пишет:

Они вычищаются сразу после создания элемента

принято это делать "ДО"

gonzales
Offline
Зарегистрирован: 13.07.2015

b707 пишет:

gonzales пишет:

На SD-карте хранится инфа об объекте в структурированных txt файлах. Я не знаю заранее, сколько объектов в определенный момент времени будет одновременно использоваться, есть только ограничение сверху (заведомо большое). Выделять память под все объекты - пустая трата ресурсов, потому как реально объектов может быть 3 или 5. При этом я должен иметь возможность обратиться к каждому из элементов. Я для удобстра использовал структуру и (видимо наивно) полагал, что динамический массив позволит мне выделять память под конкретный объект и затем ее освободить. Но походу delete затирает весь массив, а не отдельный элемент. Как быть в такой ситуации?

Да вы почти все сделали правильно, вам только массив обьектов нужно отделить от самих обьектов.

1. Описать структуру или класс для обьектов.

2. При появлении нового обьекта - память под каждый обьект выделять динамически.

3. В массиве хранить только ссылку на обьект. Массив можно сделать статическим, ибо даже 10-20 ссылок - это совсем немного байт.

4. Когда нужда в обьекте отпадает - чистите сам обьект, удаляете ссылку на него из массива (заменяете на NULL) и удаляете обьект

Я в общем-то думал, что именно так я и делаю. Структура есть, память выделяется динамически оператором new. Из того что я прочитал, я вынес, что диначеский массив - это и есть массив указателей. Если не затруднит, подскажите, как правильно описать объект и массив со ссылками

gonzales
Offline
Зарегистрирован: 13.07.2015

Клапауций 298 пишет:

gonzales пишет:

Не понятно написали, new, delete - сдесь все понятно, а что подразумевается под "а для массива еще и [] в обоих случаях. Для delete внутрь []  кол-во не указываем"???

просто сделай, как по ссылке, что я дал - нет смысла перечислять бока, что ты напорол.

Что именно сделать? Удалить весь массив delete [] TRule, так мне это не надо. Я хочу удалить объект, чтобы он не съедал память и ссылку на него в массиве

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Пока Вы не покажете код, разговор будет ни о чём.

gonzales
Offline
Зарегистрирован: 13.07.2015

Код в первом посте. Вопрос в основном теоретический, как сделать правильно.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
struct TRule {
  byte SceneID; //<- размерность byte
  byte ElseSceneID;
};

Rule[RuleID] = new TRule;
Rule[RuleID]->SceneID = JRule["ExecuteScene"]; //<-- а присваиваеться хрен знает что
/*Rule[RuleID]->SceneID = 5;*/ //<-- а почему не так
Rule[RuleID]->ElseSceneID = JRule["ElseScene"];

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

gonzales пишет:

Код в первом посте. 

Это не код, а огрызки. Хотите нормального разговора, давайте код, а если так - потрындеть ...

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

.del

Logik
Offline
Зарегистрирован: 05.08.2014

gonzales пишет:

На SD-карте хранится инфа об объекте в структурированных txt файлах. Я не знаю заранее, сколько объектов в определенный момент времени будет одновременно использоваться, есть только ограничение сверху (заведомо большое). Выделять память под все объекты - пустая трата ресурсов, потому как реально объектов может быть 3 или 5. При этом я должен иметь возможность обратиться к каждому из элементов. Я для удобстра использовал структуру и (видимо наивно) полагал, что динамический массив позволит мне выделять память под конкретный объект и затем ее освободить. Но походу delete затирает весь массив, а не отдельный элемент. Как быть в такой ситуации?

В такой ситуации вместо массива используют список. В каждой структуре хранят указатель на другую/другие структуру. Например http://victor192007.narod.ru/files/cpp_d1.html

gonzales
Offline
Зарегистрирован: 13.07.2015

По ходу сам нашел.

Как писал b707 нужно удалить ссылку на объект в массиве. 

Rule[RuleNum]=NULL;
delete Rule[RuleNum];

По крайней мере у меня такая конструкция работает абсолютно корректно

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

gonzales пишет:

По ходу сам нашел.

Как писал b707 нужно удалить ссылку на объект в массиве. 

Rule[RuleNum]=NULL;
delete Rule[RuleNum];

По крайней мере у меня такая конструкция работает абсолютно корректно

Простите, с чего Вы взяли, что она работает? Никакая память здесь не освобождается, объект остаётся в памяти. Ошибки нет, т.к. освобождение NULL - законная опреация, но она просто ничего не делает. Возьмите, наконец, MemoryExplorer и посмотрите, что творится у Вас с памятью.

Я вчера Вам писал, чтобы Вы дали нормальный код и реально собирался поработать и помочь Вам. Но кода Вы не даёте (не знаю почему), дело Ваше.

Клапауций 298
Клапауций 298 аватар
Offline
Зарегистрирован: 25.01.2018

ЕвгенийП пишет:

Но кода Вы не даёте (не знаю почему), дело Ваше.

я запретил публиковать в общий доступ секретные российские разработки. О_О

gonzales
Offline
Зарегистрирован: 13.07.2015

ЕвгенийП пишет:

gonzales пишет:

По ходу сам нашел.

Как писал b707 нужно удалить ссылку на объект в массиве. 

Rule[RuleNum]=NULL;
delete Rule[RuleNum];

По крайней мере у меня такая конструкция работает абсолютно корректно

Простите, с чего Вы взяли, что она работает? Никакая память здесь не освобождается, объект остаётся в памяти. Ошибки нет, т.к. освобождение NULL - законная опреация, но она просто ничего не делает. Возьмите, наконец, MemoryExplorer и посмотрите, что творится у Вас с памятью.

Я вчера Вам писал, чтобы Вы дали нормальный код и реально собирался поработать и помочь Вам. Но кода Вы не даёте (не знаю почему), дело Ваше.

Нормальный код 20000 строк на 25 вкладках))))

Решил добить тему, заодно вдруг кому пригодится.

Вот тестовый код

struct TRule {
  byte SceneID;
  byte ElseSceneID;
};

TRule* Rule[50];

extern int __bss_end;
extern void *__brkval;
int i;

int memoryFree()
{
  int freeValue;
  if ((int)__brkval == 0)
    freeValue = ((int)&freeValue) - ((int)&__bss_end);
  else
    freeValue = ((int)&freeValue) - ((int)__brkval);
  return freeValue;
}

void setup() {
  Serial.begin(9600);
  Serial.print("Start. Free RAM = ");
  Serial.println(memoryFree());
  Serial.println("");
  i = 0;

}

void loop() {
  i++;
  Rule[3] = new TRule;
  Rule[3]->SceneID = 3;
  Rule[3]->ElseSceneID = 5;
  Serial.print("Create object. Free RAM ");
  Serial.print(i);
  Serial.print(" = ");
  Serial.println(memoryFree());
  Rule[3] = NULL;
  delete Rule[3];
  Serial.print("Delete object. Free RAM ");
  Serial.print(i);
  Serial.print(" = ");
  Serial.println(memoryFree());
  Serial.println("");
  delay(1000);


}

Как видно, действительно память не освобождается. (((

 

gonzales
Offline
Зарегистрирован: 13.07.2015
struct TRule {
  byte SceneID;
  byte ElseSceneID;
};

TRule* Rule[50];

extern int __bss_end;
extern void *__brkval;
int i;

int memoryFree()
{
  int freeValue;
  if ((int)__brkval == 0)
    freeValue = ((int)&freeValue) - ((int)&__bss_end);
  else
    freeValue = ((int)&freeValue) - ((int)__brkval);
  return freeValue;
}

void setup() {
  Serial.begin(9600);
  Serial.print("Start. Free RAM = ");
  Serial.println(memoryFree());
  Serial.println("");
  i = 0;

  TRule *r = new TRule;
  r->SceneID = 3;
  r->ElseSceneID = 5; 
  Serial.print("Create single object. Free RAM = ");
  Serial.println(memoryFree());
  delete r;
  Serial.print("Delete single object. Free RAM = ");
  Serial.println(memoryFree());
  Serial.println("");
  delay(1000);   

}

void loop() {
  /*i++;
  Rule[3] = new TRule;
  Rule[3]->SceneID = 3;
  Rule[3]->ElseSceneID = 5;
  Serial.print("Create object. Free RAM ");
  Serial.print(i);
  Serial.print(" = ");
  Serial.println(memoryFree());
  Rule[3] = NULL;
  delete [] Rule[3];
  Serial.print("Delete object. Free RAM ");
  Serial.print(i);
  Serial.print(" = ");
  Serial.println(memoryFree());
  Serial.println("");
  delay(1000);*/


}

Странно, но даже единичный объект не удаляется из памяти или memoryFree не правильно работает

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

а если строчки 

51   Rule[3] = NULL;
52   delete [] Rule[3];
 

местами поменять? и скопки [] выкинуть?

gonzales
Offline
Зарегистрирован: 13.07.2015

Блин, ошибся, пока писал

Наоборот, сначала убиваем объект, потом вытираем ссылку.

Вот рабочий код

struct TRule {
  byte SceneID;
  byte ElseSceneID;
};

TRule* Rule[50];

extern int __bss_end;
extern void *__brkval;
int i;

int memoryFree()
{
  int freeValue;
  if ((int)__brkval == 0)
    freeValue = ((int)&freeValue) - ((int)&__bss_end);
  else
    freeValue = ((int)&freeValue) - ((int)__brkval);
  return freeValue;
}

void setup() {
  Serial.begin(9600);
  Serial.print("Start. Free RAM = ");
  Serial.println(memoryFree());
  Serial.println("");
  i = 0;

  TRule *r = new TRule;
  r->SceneID = 3;
  r->ElseSceneID = 5; 
  Serial.print("Create single object. Free RAM = ");
  Serial.println(memoryFree());
  
  delete r;
  r = NULL;
  Serial.print("Delete single object. Free RAM = ");
  Serial.println(memoryFree());
  Serial.println("");
  delay(1000);   

}

void loop() {
  i++;
  Rule[3] = new TRule;
  Rule[3]->SceneID = 3;
  Rule[3]->ElseSceneID = 5;
  Serial.print("Create object. Free RAM ");
  Serial.print(i);
  Serial.print(" = ");
  Serial.println(memoryFree());
  delete Rule[3];
  Rule[3] = NULL;
  Serial.print("Delete object. Free RAM ");
  Serial.print(i);
  Serial.print(" = ");
  Serial.println(memoryFree());
  Serial.println("");
  delay(1000);


}

 

gonzales
Offline
Зарегистрирован: 13.07.2015

Всем спасибо!!!

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

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

скобки после delete не нужны. Ты не массив удаляешь, а структурку.

gonzales
Offline
Зарегистрирован: 13.07.2015

Уже поправил, хотя так тоже отрабатывало, но скобки конечно не правильно

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

gonzales пишет:

Наоборот, сначала убиваем объект, потом вытираем ссылку.

А зачем? Зачем вообще строка 54? На что она влияет? Открою Вам страшный секрет - она лишняя. Тоже о строке 36.

Вы неправильно походите к делу и потому работаете вслепую. То, что Вы где-то взяли memoryFree - это шаг в правильном направлении, но на самом деле Вам нужно сделать две вещи:

1. Использовать конструктор и деструктор Вашего объекта для печати информации о его создании / уничтожении. Вы удивитесь насколько легче станет жить, если открыть глаза и не работать вслепую.

2. Использовать не memoryFree, а полноценный монитор памяти.

Собственно даже только с первым пунктом Вы бы давно отладились - привыкайте работать с открытми глазами, не зажмуривайте их от страха.

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

Мне не очень понятен смысл фразы "память действительно не освобождается". Если Вы хотели, чтобы память при возвращении в пул обнулялась, то таки да, этого не делается но и не должно, так что ручками.

А вот для того, чтобы не использовать занятие и освобождение памяти, добавлена возможность создавать массивы переменного размера - то, что Вам надо, с главным условием - в момент создания массива Вы должны знать его размер.

Logik
Offline
Зарегистрирован: 05.08.2014

GarryC пишет:

Мне не очень понятен смысл фразы "память действительно не освобождается".

она не возвращается в алиэкспрес.

gonzales
Offline
Зарегистрирован: 13.07.2015

ЕвгенийП пишет:

gonzales пишет:

Наоборот, сначала убиваем объект, потом вытираем ссылку.

А зачем? Зачем вообще строка 54? На что она влияет? Открою Вам страшный секрет - она лишняя. Тоже о строке 36.

Вы неправильно походите к делу и потому работаете вслепую. То, что Вы где-то взяли memoryFree - это шаг в правильном направлении, но на самом деле Вам нужно сделать две вещи:

1. Использовать конструктор и деструктор Вашего объекта для печати информации о его создании / уничтожении. Вы удивитесь насколько легче станет жить, если открыть глаза и не работать вслепую.

2. Использовать не memoryFree, а полноценный монитор памяти.

Собственно даже только с первым пунктом Вы бы давно отладились - привыкайте работать с открытми глазами, не зажмуривайте их от страха.

я так подозреваю, именно это Вы называли выше реальной помощью, такой "батя в здании" подошел и похлопал по плечу, "не ссы пацан, открой глаза и прыгай"!!!

По существу

1. Если строки 54 и 36 не нужны, возьмите код

struct TRule {
  byte SceneID;
  byte ElseSceneID;
};

TRule* Rule[50];

extern int __bss_end;
extern void *__brkval;
int i;

int memoryFree()
{
  int freeValue;
  if ((int)__brkval == 0)
    freeValue = ((int)&freeValue) - ((int)&__bss_end);
  else
    freeValue = ((int)&freeValue) - ((int)__brkval);
  return freeValue;
}

void setup() {
  Serial.begin(9600);
  Serial.print("Start. Free RAM = ");
  Serial.println(memoryFree());
  Serial.println("");
  i = 0;

  TRule *r = new TRule;
  r->SceneID = 3;
  r->ElseSceneID = 5; 
  Serial.print("Create single object. Free RAM = ");
  Serial.println(memoryFree());
  
  delete r;
  r = NULL;
  Serial.print("Delete single object. Free RAM = ");
  Serial.println(memoryFree());
  Serial.println("");
  delay(1000);   

}

void loop() {
  i++;
  if (Rule[3]!=NULL){
    Serial.println("FUCK, object still here");
  }
  Rule[3] = new TRule;
  Rule[3]->SceneID = 3;
  Rule[3]->ElseSceneID = 5;
  Serial.print("Create object. Free RAM ");
  Serial.print(i);
  Serial.print(" = ");
  Serial.println(memoryFree());
  delete Rule[3];
  //Rule[3] = NULL;
  Serial.print("Delete object. Free RAM ");
  Serial.print(i);
  Serial.print(" = ");
  Serial.println(memoryFree());
  Serial.println("");
  delay(1000);


}

и запустите. я с этого начал пост, что просто delete работает наполовину!!!

2. Накой мне полноценный монитор памяти? Чем конкретно плох memoryFree?

3. Страшная тайна, new и delete это и есть конструктор и деструктор, только тссс!!!

 

PS. Не люблю холивар, но уж как-то совсем все плохо. Особенно товарищ с "алиэкспрессом" порадовал, верх профессионализма

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

3. Страшная тайна, new и delete это и есть конструктор и деструктор, только тссс!!!

Никому такова не говори больше, это не совсем так. Вернее, совсем не так. 

gonzales
Offline
Зарегистрирован: 13.07.2015

DetSimen пишет:

3. Страшная тайна, new и delete это и есть конструктор и деструктор, только тссс!!!

Никому такова не говори больше, это не совсем так. Вернее, совсем не так. 

Есть ли ссылка на какой-нить RTFM по этому поводу? 

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

эти функции, несколько сложнее, чем просто вызов конструктора и деструктора. 

RTFM -> труп Страуса. Прям вот самый штонинаесть первоисточник. 

Клапауций 298
Клапауций 298 аватар
Offline
Зарегистрирован: 25.01.2018

gonzales пишет:

3. Страшная тайна, new и delete это и есть конструктор и деструктор, только тссс!!!

ты не совсем точно понял смысл рекомендации - пропиши в структуру конструктор и деструктор, функциями которых будет печать("конструктор запущен"), печать("деструктор запущен").

чиста для удобства отладки - потом закомментишь.

Клапауций 298
Клапауций 298 аватар
Offline
Зарегистрирован: 25.01.2018

gonzales пишет:

Не люблю холивар...

а, придётся... О_О

gonzales
Offline
Зарегистрирован: 13.07.2015

Я может конечно безгранично туп, но вот вырезка из MSDN

class String {  
public:  
   String( char *ch );  // Declare constructor  
   ~String();           //  and destructor.  
private:  
   char    *_text;  
   size_t  sizeOfText;  
};  
  
// Define the constructor.  
String::String( char *ch ) {  
   sizeOfText = strlen( ch ) + 1;  
  
   // Dynamically allocate the correct amount of memory.  
   _text = new char[ sizeOfText ];  
  
   // If the allocation succeeds, copy the initialization string.  
   if( _text )  
      strcpy_s( _text, sizeOfText, ch );  
}  
  
// Define the destructor.  
String::~String() {  
   // Deallocate the memory that was previously reserved  
   //  for this string.  
   if (_text)  
      delete[] _text;  
}  
  
int main() {  
   String str("The piper in the glen...");  
}  

Как видим в конструкторе используется оператор new, а в деструкторе delete. (мопед не мой, я просто разместил объяву)

Но только это все для классов, мне зачем такие сложности, если тут просто структура? И какой смысл делать отдельный конструктор, если мне, чтобы убедиться, что объект создан достаточно того, что я вижу изменение используемой памяти, ну или на крайняк после создания объекта и присвоения значений вывести в монитор Serial.println(Rule[3]->SceneID);

 

Клапауций 298
Клапауций 298 аватар
Offline
Зарегистрирован: 25.01.2018

gonzales пишет:

Как видим в конструкторе используется оператор new, а в деструкторе delete. (мопед не мой, я просто разместил объяву)

при чём здесь утилизация переменных класса к отладке твоего кода?

gonzales пишет:

мне зачем такие сложности, если тут просто структура?

да хоть Путин - как ты узнаешь, что делетнул его, если не видишь - упал или стоит?

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

gonzales пишет:

я так подозреваю, именно это Вы называли выше реальной помощью, такой "батя в здании"

Не понял о чём это. Какой мой пост Вы имеете в виду?

gonzales пишет:

я с этого начал пост

Неправда, Вы начали свой пост с того, что НЕ опубликовали законченный скетч, а я просто умолял Вас, ну опубликуйте же скетч, я хочу Вам помочь, но без законченного скетча это невожно! (мои посты #12 и #15)

Теперь, Вы слава Богу, смилостивились, и смогу Вам помочь несмотря на ... несколько недружественный тон Ваше последнего поста.

gonzales пишет:

2. Накой мне полноценный монитор памяти? Чем конкретно плох memoryFree?

Если Бы Вы его хотя бы раз запустили, этого вопроса бы не было. Но Вы советов не слушаете, они Вам не нужны. Я вот не понимаю "накой" Вы вообще сюда пришли, если знаете лучше нас что Вам "накой", а что "не накой"?

gonzales пишет:
3. Страшная тайна, new и delete это и есть конструктор и деструктор, только тссс!!!

Примите галаперидольчику и прекратите бредить.

gonzales пишет:
Особенно товарищ с "алиэкспрессом" порадовал, верх профессионализма

Здесь все старожилы знают, что у меня сложные отношения с этим "товарищем", но это наши с ним разборки. Что же до Вас, то, по части "профессионализма", Вам до него как до Луны. Если Вы реально хотите чему-то научиться, а не прокачать понты, то Вам лучше задавать таким людям вежливые вопросы и внимательно слушать ответы, а не задирать хвост "накой мне".

gonzales пишет:

По существу

Ну, а по существу. Обычно, после постов в таком тоне, как был у Вас, я отсылаю человека к универсальной документации на все случаи жизни и ухожу из темы, но вот именно Вам мне почему-то реально хочется помочь, хотя, вроде, и не должно бы. Не знаю почему, считайте это капризом. Я объясню Вам Вашу ошибку реально и серьёзно. Правда при этом не буду выбирать выражений. Хотите учиться - учитесь, хотите обижаться - обижайтесь, дело Ваше. 

Итак, долгожданный код, о котором я Вас дважды просил.

struct TRule {
  byte SceneID;
  byte ElseSceneID;
};

TRule* Rule[50];

extern int __bss_end;
extern void *__brkval;
int i;

int memoryFree()
{
  int freeValue;
  if ((int)__brkval == 0)
    freeValue = ((int)&freeValue) - ((int)&__bss_end);
  else
    freeValue = ((int)&freeValue) - ((int)__brkval);
  return freeValue;
}

void setup() {
  Serial.begin(9600);
  Serial.print("Start. Free RAM = ");
  Serial.println(memoryFree());
  Serial.println("");
  i = 0;

  TRule *r = new TRule;
  r->SceneID = 3;
  r->ElseSceneID = 5;
  Serial.print("Create single object. Free RAM = ");
  Serial.println(memoryFree());

  delete r;
  r = NULL;
  Serial.print("Delete single object. Free RAM = ");
  Serial.println(memoryFree());
  Serial.println("");
  delay(1000);

}

void loop() {
  i++;
  if (Rule[3] != NULL) {
    Serial.println("FUCK, object still here");
  }
  Rule[3] = new TRule;
  Rule[3]->SceneID = 3;
  Rule[3]->ElseSceneID = 5;
  Serial.print("Create object. Free RAM ");
  Serial.print(i);
  Serial.print(" = ");
  Serial.println(memoryFree());
  delete Rule[3];
  //Rule[3] = NULL;
  Serial.print("Delete object. Free RAM ");
  Serial.print(i);
  Serial.print(" = ");
  Serial.println(memoryFree());
  Serial.println("");
  delay(1000);
}

Вы, видимо решили, что освобождение памяти не работает на том основании, что условие в строке 46 остаётся истинным. Это бред сивой кобылы. Это условие - это НЕ проверка факта освобождения памяти.

В Rule[3] находится адрес некоторого куска памяти. Вы туда его (адрес) поместили, когда объект создавали. Он (адрес) находится там независимо от того занята эта память или свободна. Вы можете уже освободить память, но адрес (освобождённого куска) там остаётся. Так что Ваша строка 46 ровным счётом ничего не проверяет, от слова "совсем".

Если Вы действительно хотите проверить факт особождения памяти, то слушайте что Вам говорят, а не пытайтесь учить профессионалов что такое конструктор и деструктор. Смотрите, как это делается. Я переписываю Ваш код добавив туда конструктор и деструктор о которых я говорил:

struct TRule {
	// КОНСТРУКТОР
	TRule(void) {
		Serial.print("Oject created: ");
		Serial.println((unsigned)this);
	}
	// ДЕСТРУКТОР
	~TRule(void) {
		Serial.print("Oject destroyed: ");
		Serial.println((unsigned)this);
	}
	byte SceneID;
	byte ElseSceneID;
};

TRule* Rule[50];

extern int __bss_end;
extern void *__brkval;
int i;

int memoryFree()
{
  int freeValue;
  if ((int)__brkval == 0)
    freeValue = ((int)&freeValue) - ((int)&__bss_end);
  else
    freeValue = ((int)&freeValue) - ((int)__brkval);
  return freeValue;
}

void setup() {
	Serial.begin(115200);
	Serial.print("Start. Free RAM = ");
	Serial.println(memoryFree());
	Serial.println("");
	i = 0;
	
	TRule *r = new TRule;
	r->SceneID = 3;
	r->ElseSceneID = 5; 
	Serial.print("Create single object. Free RAM = ");
	Serial.println(memoryFree());
	
	delete r;
	r = NULL;
	Serial.print("Delete single object. Free RAM = ");
	Serial.println(memoryFree());
	Serial.println("");
	delay(1000);   
}

void loop() {
	i++;
	if (Rule[3]!=NULL){
	 Serial.println("FUCK, object still here");
	}
	Rule[3] = new TRule;
	Rule[3]->SceneID = 3;
	Rule[3]->ElseSceneID = 5;
	Serial.print("Create object. Free RAM ");
	Serial.print(i);
	Serial.print(" = ");
	Serial.println(memoryFree());
	delete Rule[3];
	//Rule[3] = NULL;
	Serial.print("Delete object. Free RAM ");
	Serial.print(i);
	Serial.print(" = ");
	Serial.println(memoryFree());
	Serial.println("");
	delay(1000);
}

Теперь при каждом создании объекта я вижу, что он создаётся и вижу его адрес. А при удалении объекта, я также вижу адрес удаляемого объекта. Смотрим:

Start. Free RAM = 1528

Oject created: 766
Create single object. Free RAM = 1524
Oject destroyed: 766
Delete single object. Free RAM = 1528

Oject created: 766
Create object. Free RAM 1 = 1524
Oject destroyed: 766
Delete object. Free RAM 1 = 1528

FUCK, object still here
Oject created: 766
Create object. Free RAM 2 = 1524
Oject destroyed: 766
Delete object. Free RAM 2 = 1528

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

Теперь я позволю себе поудалять из кода глупости с присваиванием NULL и Вашу бредовую проверку

struct TRule {
	// КОНСТРУКТОР
	TRule(void) {
		Serial.print("Oject created: ");
		Serial.println((unsigned)this);
	}
	// ДЕСТРУКТОР
	~TRule(void) {
		Serial.print("Oject destroyed: ");
		Serial.println((unsigned)this);
	}
	byte SceneID;
	byte ElseSceneID;
};

TRule* Rule[50];

extern int __bss_end;
extern void *__brkval;
int i;

int memoryFree()
{
  int freeValue;
  if ((int)__brkval == 0)
    freeValue = ((int)&freeValue) - ((int)&__bss_end);
  else
    freeValue = ((int)&freeValue) - ((int)__brkval);
  return freeValue;
}

void setup() {
	Serial.begin(115200);
	Serial.print("Start. Free RAM = ");
	Serial.println(memoryFree());
	Serial.println("");
	i = 0;
	
	TRule *r = new TRule;
	r->SceneID = 3;
	r->ElseSceneID = 5; 
	Serial.print("Create single object. Free RAM = ");
	Serial.println(memoryFree());
	
	delete r;
	Serial.print("Delete single object. Free RAM = ");
	Serial.println(memoryFree());
	Serial.println("");
	delay(1000);   
}

void loop() {
	i++;
	Rule[3] = new TRule;
	Rule[3]->SceneID = 3;
	Rule[3]->ElseSceneID = 5;
	Serial.print("Create object. Free RAM ");
	Serial.print(i);
	Serial.print(" = ");
	Serial.println(memoryFree());
	delete Rule[3];
	Serial.print("Delete object. Free RAM ");
	Serial.print(i);
	Serial.print(" = ");
	Serial.println(memoryFree());
	Serial.println("");
	delay(1000);
}

Смотрим, что получается

Start. Free RAM = 1552

Oject created: 742
Create single object. Free RAM = 1548
Oject destroyed: 742
Delete single object. Free RAM = 1552

Oject created: 742
Create object. Free RAM 1 = 1548
Oject destroyed: 742
Delete object. Free RAM 1 = 1552

Oject created: 742
Create object. Free RAM 2 = 1548
Oject destroyed: 742
Delete object. Free RAM 2 = 1552

Oject created: 742
Create object. Free RAM 3 = 1548
Oject destroyed: 742
Delete object. Free RAM 3 = 1552

Видим, что память как была 1552 в начале, так и остаётся после каждого удаления объекта. Объект постоянно создаётся на одном и том же месте - по адресу 742, значит это место аккуратно освобождается и каждый раз оно же выделяется для вновь создаваемого объекта.

Вы согласны. что всё работает как часы? Думаю, оно у Вас и работало нормально, просто Вы придумали какой-то бред, считая его проверкой и на основании этого бреда запаниковали. Если бы Вы ещё вчера показали мне код, как я Вас просил, проблема бы уже давно забылась бы!

Теперь я готов ответить на Ваши вопросы, но вежливые и по делу, т.е. продолжить нормальную профессиональную беседу. При любом наезде или попытке поучить меня, что такое конструктор, Вы будете посланы туда, куда я обычно в таких случаях посылаю (Выше об этом было). И никакого холивара не будет. У нас разные весовые категории.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

gonzales пишет:

Как видим в конструкторе используется оператор new, а в деструкторе delete. (мопед не мой, я просто разместил объяву)

А ещё и там, и там используется оператор if и что с того? Делаем вывод, что if - это и есть конструктор (и деструктор заодно)? 

gonzales пишет:

Но только это все для классов, мне зачем такие сложности, если тут просто структура? 

Структура (struct) - такой же точно класс как и class. Разница только в умолчательный аттрибутах методов и свойств.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

gonzales пишет:

Я может конечно безгранично туп,

Не знаю, туп ты или не туп, но то, что очень мало знаешь, и при этом хамоват - это точно.

Logik
Offline
Зарегистрирован: 05.08.2014

gonzales пишет:

PS. Не люблю холивар, но уж как-то совсем все плохо. Особенно товарищ с "алиэкспрессом" порадовал, верх профессионализма

Это хороше что порадовал "алиэкспрессом",  проффесиональный подход из #17 вам ведь оказался совершенно неинтересен. Значить бум развлекатся, писать говнокод, холиварить о конструкторе ))) Пятница ведь!