не работает инициализация класса через new
- Войдите на сайт для отправки комментариев
Чт, 30/07/2020 - 00:10
Подскажите, почему вот такой код работает
My_Class a(A,B,C); void setup() { a.init(); } void loop() { a.run(); }
а вот такой - компилируется без единого предупреждения, но не работает?
My_Class *a; void setup() { a = new My_Class(A,B,C); a->init(); } void loop() { a->run(); }
может при такой инициализации какой секрет есть?
Уточняю - внутри конструктора есть выделение динамического массива через malloc. пробовал переносить malloc из конструктора в init() (прочитал, что конструктор при непосредственном вызове и через new работает немного по разному... не помогло)
Прошу прощения, что выкладываю псевдокод - реальный слишком лохматый, раскидан по шести исходным фалам... Если по этому псевдо ничего сказать нельзя - так и скажите. Буду рыть сам.
нельзя
нельзя
правильно я понимаю, что между этими методами инициализации никакой разницы нет вообще? - я вроде много раз использовал и тот и другой - первый раз столкнулся с различиями.
Вот реально в огромной программе меняю только эту инициализацию класса. Эй богу не вру :) Первый код работает, второй нет.
Ладно, спасибо, покопаюсь сам.
В псевдокоду все в порядке. Можете добавить создать простой класс, который, например, печатает строку в serial , и убедитесь сами.
Разница есть, конечно. В первом случае класс живет на стеке, во втором в куче.
В псевдокоду все в порядке. Можете добавить создать простой класс, который, например, печатает строку в serial , и убедитесь сами.
я сам знаю что должно работать :)
написал выше - много раз пользовал и то и то.
Блин, значит где в остальном коде очень хитрый косяк...
Разница есть, конечно. В первом случае класс живет на стеке, во втором в куче.
а это направление для поиска. "Нерабочесть" второго варианта выглядит так, будто динамический буфер не выделился или выделился неверно...
а это направление для поиска. "Нерабочесть" второго варианта выглядит так, будто динамический буфер не выделился или выделился неверно...
А возвращаемый malloc-ом указатель ты на NULL проверяешь?
Ну, хоть конструктор-то покажите! И вообще, сделайте маленький пример. Или маленькие работают? Если так то надо "лохматый" смотреть.
Ну, хоть конструктор-то покажите! И вообще, сделайте маленький пример. Или маленькие работают? Если так то надо "лохматый" смотреть.
показываю:
Конструктор
Деструктор (добавил только когда появились проблема, раньше не было
члены и методы (сокращено)
собственно, полный код библиотеки есть на Гитхабе , правда там версия чуть старше, но в целом текст совпадает
А возвращаемый malloc-ом указатель ты на NULL проверяешь?
нет, не проверял. Теперь, конечно, проверю... Но вроде памяти дофига, статические переменные занимают 14% ОЗУ, динамические - еще от силы процентов пять...
Кроме того, в первом-то варианте все работает, значит памяти хватает?
Не, так не пойдёт. У конструктора 7 параметров без умолчательных значений, а вызове в первом посте - всего три. Он бы не скомпилировался.
Давайте полный пример, а то каша какая-то.
тогда полный пример вот
https://github.com/board707/DMD_STM32/blob/master/examples/STM32F1/dmd_cyr_chars/dmd_cyr_chars.ino
Только есть нюанс - на этом примере я не проверял, проявляется ли тут описанная проблема.
Я понимаю, что это хамство по вашей классификации, так что давайте я для начала сам попробую :)
Давайте :-)
А нормально вообще SPIClass передавать по значению?
А нормально вообще SPIClass передавать по значению?
согласен, может не слишком эффективно. Но он же небольшой. Хотя надо будет попробовать по ссылке.
Первая можно сказать фундаментальная ошибка это b707 положил большой болт на правило пяти. А это значит что компилятор будет делать в таких ситуациях как ему удобно. Не хотите их писать, так закройте их компиляцию.
https://riptutorial.com/ru/cplusplus/example/5421/правило-пяти
Первая можно сказать фундаментальная ошибка это b707 положил большой болт на правило пяти.
Круто!
давайте я для начала сам попробую :)
Давайте :-)
попробовал, пример с гитхаба (из стабильного релиза библиотеки) работает в обоих вариантах, из беты - во втором случае выводит на матрицу "молоко" вместо картинки. Значит я что-то в последнем релизе напортачил...
Будем искать.
Первая можно сказать фундаментальная ошибка это b707 положил большой болт на правило пяти. А это значит что компилятор будет делать в таких ситуациях как ему удобно. Не хотите их писать, так закройте их компиляцию.
https://riptutorial.com/ru/cplusplus/example/5421/правило-пяти
про правило пяти прочитал, спасибо (впервые слышу, но в принципе все понятно и логично). А вот фразу про "не хотите их писать - закройте компиляцию" - не понял. Что мне нужно закрыть?
Чудеса
После двух пересборок глюк пропал, теперь и мой изначальный пример работает в обоих вариантах.
ХЗ что это было... может когда менял вызовы методов через точку на вызовы через стрелку, где-то опечатался... бывают такие опечатки, что фиг найдешь... если при компиляции ошибок нет.
Объявить их в классе и написать delete. Это наследие осталось когда классы были структурами и компилятор их создавал автоматически. Точнее и сейчас создаст ,если не закрыть их создание. Конечно можно сказать что пользователь с дуру не начнет создавать класс копированием исходного. Но ли. Пользователи бывают очень умными или очень дурными и компилятор начнет создавать то что не закрыто.
Например, допустим вот здесь кнопка в момент включения питания НЕ нажата. Неясно какое именно значение в строке №11 получит m_State, т.к. не определено кто первым инициализируется: thePin или theButton. Пример глупый - только, чтобы выпятить проблему.
Более того, порядок их инициализации может измениться при очередной компиляции от любого чиха в исходнике.
А вот в таком варианте всё чётко и однозначно.
Поэтому, когда нужна сложная инициализация с побочными эффектами, лучше использовать что-то однозначное. Через указатели, конечно, слишком круто - обычно сложную инициализацию делают в специальном методе типа "init()" или "begin()", а не в конструкторе, а уж методы вызывают в правильном порядке.