Dziwny problem z kodem w C (gcc mips/pic32)

May 17, 2023 Last reply: 3 years ago 169 Replies

To wystarczy aby "trzeba zacząć C++ używać".

W przypadku oznaczania tablicy przez std::size, należy się jeszcze upewnić, że kompilator i bibliteki są zgodne, bodaj, z C++17, lub, że ma się 20 letni kompilator wspierany przez 20 letni boost, jeśli z jakiegoś powodu ma się 20 letni kompilator.

W sensie że zamiana dwóch literek na dwa + to śmiertelna rana? Jeśli to coś popsuje, to i tak miałeś popusty kod wcześniej. Zwyczajowo nic nie popsuje.

A mówią, że nie ma darmowych obiadów.

heby snipped-for-privacy@poczta.onet.pl> napisał(a):

I od tego Marek zostanie programistą C++?

Nie. Zapewne dlatego wyciałeś cycta wyżej. Od tego może "zacząć C++ używać".

heby snipped-for-privacy@poczta.onet.pl> napisał(a):

Wyciąłem, bo pisząc o zaczęciu nie miałem na myśli wykonania kroku, który tak naprawdę nic nie zmienia. Język kodu nie zależy od nazwy kompilatora. Ba, możesz nawet napisać kod i go nie skompilować. Oni tego nie sprawdzają :) Podobnie czytając książkę o programowaniu rozpoznasz język bez używania żadnego narzędzia. Kolega KS zacznie używać C++ gdy zacznie używać jego mechanizmy i porzuci nawyki z C.

Krok ten zmienia bardzo wiele. Nagle nie masz wymówki, że się nie da pisać lepiej.

W momencie jak masz C++, zrobienie buga na sizeof jest dalej możliwe, ale znacząco bardziej wstydliwe, a po kilku latach praktyki, praktycznie trudne.

Trzymanie się tej meldy "ja od zawsze pisałem w C i nie mogę używać std::size" jest tym mniej sensowne im bardziej rozumiesz jaki jest koszt przejścia na C++. Zerowy, choć są koszta ideologiczne.

To częsciowo prawda, g++ i gcc tak naprawdę róznią się tylko detalami.

Filozofujesz.

Prawda taka, że społecznośc programistów embedded zazwyczaj jest o mały krok od zamiany kijka na siekierkę i to za friko. Ale z jakiejś przyczyny nie chcą. I nikt, do dzisiaj, nie wyjaśnił mi jaki koszt ponoszą zmieniajac 2 literki w nazwie kompialtora i dostając masę nowych ficzerów.

Nie. Mechniazmów C++ możesz używać dowolnych, w dowolnym momencie. Nikt nie porzuca C, nie ma takiej potrzeby. W C++ jest masa ułatwień, któe znakomicie przydadzą się w C bez potrzeby rezygnacji i dysonansu ideologicznego. std::size to jedno z setek, użytecznych w embedded, ułatwień, za darmo.

heby snipped-for-privacy@poczta.onet.pl> napisał(a):

Ciekawe stwierdzenie jak na kogoś, kto daje poradę odnoszącą się do innego języka niż używa pytający :) A potem rozważasz jaka super jest zmiana gcc na g++ w Makefile.

czwartek, 18 maja 2023 o 15:04:31 UTC+2 Marek napisał(a):

A, OK, dzięki, to całkiem fajne, choć w typowych zastosowaniach uC przydaje się tylko do debugowania przekroczeń pamięci - ale to też się przyda.

Ja zrobiłem na ATmegę dwa wątki wywłaszczane (no bo procesy bez ochrony pamięci są bez sensu). Ale nie mam pomysłu, do czego użyć tego w praktyce.

Linux, przy całym swym bogactwie, ma jedną wadę - nie jest systemem czasu rzeczywistego. A olbrzymia większość tego, co robiłem na uC, jest przynajmniej soft real-time. I w sumie nic dziwnego - od nie-real-time mamy PC-ty z Linuxem.

Jako przycisku do papieru ;>

Mój zaraz będzie 17-letni. Prawie "stara dupa" ;>

Nie, odwrotnie. Zmienić dwie literki - proste, ale nie wystarczy. Może wystarczą następne kroki - ale one są już o wiele, wiele trudniejsze.

Zaś "zwyczajowo" - to samo raczej nic nie poprawi. Popsuć może.

Pytający używa subsetu C++ o nazwie C, nie posiadający żadnych widocznych zalet względem pełnego setu.

Istnieje bezpieczny i przeznaczony do takich zastosowań element języka poza tym subsetem.

Przeniesięnie się z subsetu do przestrzeni gdzie istnieje to rozwiązanie jest obarczone zerowym kosztem.

W przestrzeni tej istnieje też wiecej rozwiązań probemów, o których jeszcze nie wiesz, że są problemami rozwiązanymi 20 lat temu.

Bo to, co zgrabnie wyciąłeś, okresla koszt "zacząć C++ używać". To nie jest operacja zatrzymująca firmę na miesiąc. To operacja, której wiekszosc programistów nawet nie zauważy. Dlatego wymówka "zacząć C++ używać" wymaga odpowiedzi, bo często podczas dysput z embedowcami pojawia się jako heroiczny wysiłek i zwiększenie wsadu do flasha o gigabajty w/g opini zasłyszanej od kolegi szwagra z sąsiedniej firmy.

A co jeszcze musisz zmienić *zanim* zaczniesz używać std::size, poza "++"?

Możesz podać listę tych kroków?

A co może popsuć?

Niestety da się również pisać gorzej.

Wciąż nie możesz zrozumieć, że pisząc o C++ musisz mieć w świadomości, że to jest cały C++, a nie tylko wybrane przez ciebie, ułatwiające życie mechanizmy. Wtedy to były jakiś heby++. Ale nie C++. Może nie masz traumy ze studiów ze zmuszaniem do stosowania bzdur jako sztuki dla sztuki. Mnie to prześladowało jeszcze po studiach, jak kiedyś byłem na "rekrutacji" (z bardzo fajną rekruterką - więc choćby dlatego warto było, pozdrowienia ;) to dostałem da testy - z Javy i C++. Możliwe, że jestem niedouczony, ale z Javy poszedł jak z płatka, a z C++ normalnie wytrzeszcz: "to tak można?!?!jeden!"

I mi brakuje właśnie czegoś takiego jak kompilowana java na uC. Było coś w podobie zwanego JavaME - ale padło.

Jak piszesz samemu to możesz sobie dyscyplinę typu: "używam TYLKO tego, tego i tego z C++" narzucić. Ale w zespole zaraz zaczną odwalać bzdury, "bo w C++ tak można". Tak jak kiedyś byłem na rozmowie o pracę z takimi dwoma, co mieli biuro w KC, chodziło o J2ME i mocno komentowali o takich, co na J2ME alokują sobie tablice po 2MB...

Więcej nie ma, poza przekroczeniem Rubikonu - takim, że przestajesz powoli mieć możliwość odwrotu do C, a możesz nie mieć tyle fartu co Juliusz Cezar.

To ja zapytam z drugiej strony - co rozwiąże używanie TYLKO std::size, poza bugami na sizeof? Ogólnie to średnio inteligentny matoł, który przesiedział trochę dupogodzin nad bugiem na sizeof (szczególnie na embedded, bo pod OS pierwsze użycie gdb to naprawdę jest satori), zapamięta to sobie na całe życie - inaczej się na programistę i tak nie nadaje, a nie sądzę, byśmy mieli ich na tyle mało, że trzeba pytać ludzi z działu wprowadzania danych, czy chcą się nauczyć programowania.

A z trzeciej strony pozwolenie na C++ to otwarcie nowej Puszki Pandora. Tu dopiero możesz się dowiedzieć, co to jest prawdziwy bug, a nie jakiś tam sizeof.

Jak zwykle - "jeśli działa, nie naprawiaj". Sprawdzić, czy nie kobieta (poza Kopernik, Einstein i Curie-Skłodowska ;).

Tak, ale to już problem białkowy, a nie ograniczenia języka. Wystapuje w każdym języku. No może poza perlem, tam pisanie bardzo dobrze jest nieodróznialne od pisania najgorzej.

Bzdura do kwadratu.

Piszesz w C.

Masz problem, który można elegancko i czytelnie rozwiązać C++.

Używasz C++ w tym jednym miejscu.

Reszta dnia wolnego.

Czyli to problem ideologiczny. Nie możesz uwierzyć, że można pisać po staremu i tam gdzie C++ się przydaje - użyć go. Musi być albo skrajna prawica albo lewica. Recjonalizm zakazany.

Po prostu ich nie rozumiesz i to całkowicie zrozumiałe. Jak zaczniejsz używać, szczególnie jeśli ktoś pokaże Ci jak, zrozumiesz, że pewne konstrukcje w C są najzwyczajniej niebezpieczne i prowadzą do sytuacji niewykryanych przez kompilator, jak w tym watku.

Pisanie w C to pisanie w asemblerze, podługując się nieskopoziomowymi instrukcjami.

Pisanie we współczesnym C++ polega na wyrażaniu potrzeb w sposób wysokopoziomowy. Zamaist "potrzebuję wiedziec ile to zajmuje ramu i potem se podziele" piszesz "potrzebuje wiedzieć jakie to jest duże". To jest bezpieczniejsze.

Do tego stopnia, że w jednym z coding standardów jakie miałem okazję czytać, używanie sizeof w pętli for jest wykrywane przez linter na etapie review. Ktoś widocznie miał dośc poprawiania takich bzdur.

Więc to problem ideologiczny.

Czyli możesz się w wolnej chwili doedukować. Powiększawie warsztatu programistycznego to tylko plusy. Tym bardziej, że za friko.

Nie chcesz tego. Semantyka referencji i zarządzanie pamięcią w Javie nie nadaja się do mikrokontrolerów, szczególnie do zastosowań realtime, mimo wielu prób wciśnięcia Javy do małych uC. Za to C++ jak najbardziej pasuje, bo jest zdecydowanie bliżej sprzętu.

Tak. To się nazywa coding standard, review, lint. Nie masz takiego zestawu w firmie?

Nie. Od tego jest code review + coding standard. Choć przyznaje, że to pytanie/opinia czasem się pojawi, szczególnie jak zakaz idityczny. Na przykład "nie wolno używać C++ bo go nie rozumiem".

I znowu ten sam argument bez śladu sensu. To, że ktoś w C++ allokuje za dużo, to wina biedy intelektualnej programisty, a nie wina C++. C++ to tylko powiększenie składni o masę użytecznych rzeczy. Nie chroni przed debilizmem. Ale czasem wrzaśnie na etapie kompilacji o jakimś fuckupie, gdzie C przełknie bez popijania. I jak wstawisz w to zdanie "Java" zamiast "C++" to dalej będzie prawda.

Po co chcesz wracać do C? Możesz podać 1 racjonalny powód?

Dokładnie to.

Jest masa innych rozwiązań innych problemów. Każdy znajdzie coś dla siebie.

Mój ulubuiony z gatunku "ło, to się tak da?", który jest z drugiej strony, z kretaywnego wykorzystania C++:

Masz programistę C, ideologa, który prawie całe życie pisał miganie diodami w 8051.

W efekcie czego masz taki kod:

#define FOO_FLAG 1<<6 #define BAR_FLAG 1<<3 #define OUT_FLAG 1<<2

i funkcję:

void setFlags( int flags, int extra_flags );

No i które flags przyjmują jakie define?

To przykład z typowego systemu embedded.

Czy wiesz, że dzięki magii C++ możesz napisać funkcję setFlags, bez śladu narzutu w runtime, która uniemozliwi podanie nieprawidłwej flagi do zmiennej i bedzie to wykrywane na etapie kompilacji?

Pomyłka używania flag z powodu używania idotycznych #define to znaczący problem w embedded i możesz go elegancko rozwiązać w C++. Wymaga to nieco kodu o dość skomplikowanej budowie, ale dla użytkownika końcowego jest to trywialne w użyciu.

To jest raz napisane za darmo. Nagle niwelujesz masę problemów w różnych miejscach.

Tego nie da się zrobic w C, chyba że będziesz używał jakiegoś postprocessingu C.

Tutaj wlaśnie się różnimy. Dla mnie to siedzenie nad debuggerem razy ilość trywialnych problemów załatwionych w C++ to koszta, które nie uczą niczego innego, jak tylko masy iditycznych zakazów. To przypomina naukę za pomocą bata. Może i skuteczna, ale koszty ponosi pracodawca, a pracownik ma poczucie orania po polu pełnym min.

Możesz podać przykład, co okromnego stanie się po pozwoleniu używania C++ czego nie da się spierniczyć w C?

Nie, to najzwyczajniej nie prawda. Służę własną statystyką moją i kilkudziesięciu ludzi jakich znam. Koszt szukania błedu w dużym systemie w C jest dramatycznie droższy, od systemu w C++. Głównie z powodu znacząco wyższej kultury pisania, opierajacej się o unit testy, abstrakcje itp detale, których w C nie ma, a jak są, to są grubym workaroundem zazwyczaj wynajdującym C++ za pomocą makr i asemblera.

Pracuję w C++ w ogromnym oprogramowaniu. Oprogramowanie to zawiera również legacy C. Nie, nie chciałbyś tam debugować.

Czyli czysta ideologia. Masz za darmo siekiere, ale walenie patykiem o drzewo też działa, wiec po co zmieniać.

Czyli to, że w C można pisać gorzej, to problem języka, a to, że w C++ można pisać gorzej, to tylko problem białka?

Reszta dnia na kotrolowanie tego, czy ktoś inny nie użył więcej z C++ niż odpuszczasz.

Sklonuj się to się uda. Ja zawsze chciałem mieć brata bliźniaka (niekoniecznie chciałbym mieć przy tym na imię Jarosław) - to bardziej realne niż 4 ręce.

Pewne konstrukcje w C++ są jeszcze bardziej niebezpieczne. I ogólnie C++ jest jeszcze bardziej niebezpieczne, bo zawiera wszystkie niebezpieczeństwa C, plus jeszcze dodatkowe z C++.

Byś może rozmawiamy o zupełnie różnych C++.

C++ minus to, co odwala linter, to już nie jest C++. I tu dochodzimy do kosztów wprowadzenia C++ w firmie. Np. taki linter. I nowy coding standard. To koszty niezaprzeczalne. Zyski - możliwe, lecz niepewne. Bliskie pracy zespolonej.

Hmm, a we "współczesnym" C++ nie ma czegoś w rodzaju std::garbageCollector? Czym się różnią referencje w Javie i wskaźniki/referencje w C++? Możliwością statycznej alokacji w C++? To sobie w Javie stwórz i nie kasuj, będzie tam samo, a nawet lepiej, bo jakbyś chciał zacząć kasować to odchodzi jedno z największych bugo-bagien.

Ja sam sobie sterem, żeglarzem, okrętem. Ale jeszcze raz - czy coding standard, review, lint są za darmo? Może są, daj namiar na jakiś opensource czy GNU.

I dobrze, w pełni się z tobą zgadzam - narzędzi trzeba umieć używać. Ale to kosztuje.

Kompilacji? Raczej lintowania. I mając do wyboru C oraz C++ jako nadzbiór C - wybiorę jednak C, mniejszy stopień komplikacji łatwiej badać.

No a jak będzie nowe pokolenie to już nie będą musieli sięmieścić w pojedynczych kB RAM. Trzeba im tylko jako spadek zostawić dobry OS, inaczej rakiety zaczną spadać. Może to i się do pokoju światowego przyczyni, takie kacapy nie będą miały dostępu do odpowiednio mocnych uC - takie z laktatorów nie wystarczą...

Nie. W obu można pisac źle. W C++ jest to tak samo łatwe jak w C. Ale jednocześnie w C++ istnieją techniki programowania, wymuszajace pisanie dobrze i bez absuradlnych błedów, jak z watku. Nie da się ich stosować w C, ale można je stosować w C++. Niektóe lintery je wymuszają.

Pierwsza z brzegu z technik wspomagających jakość, za darmo: RIIA.

Innymi słowy w każdym jezyku można pisać dziadowski kod, ale niektóre języki aktywnie mogą temu przeciwdziałać lub przynajmniej mają do tego narzędzia zamiast pistoletu na wodę C.

To się nazywa review i jesli pracujesz w firmie robiącej coś wiecej niż miganie diodami, to na pewno jakaś formę review kodu masz. I kontrolujesz kod współpracowników, czy on jest w C czy C++ w sposób formalny już teraz.

Masz review, prawda?

Nie rozumiem po co. Pisanie w C++ oszczędza również czas. Nie musisz co chwile wynajdywać kwadratowych kół albo emulować C++ na makrach.

Bo zdecydowana większosc kodu embedded, którą widziałem w życiu, to emulacja C++ na makrach, generatorach kodu i fikusnych konstrukcjach.

Dawniej uważałem to za śmieszne, ale dzisiaj, po doświadczeniu zawodowym jakie mam, uważam to za poważny problem tej branży.

"Nie, bo nie, napisze to sam".

Które?

Podaj przykład takiej konstrukcji w C++, która jest niebezpieczna i czai się jak mina na biednego asemblerowca z C.

To wrażenie odnoszę zawsze, kiedy gadam z embedowcami. Był tu taki jeden kiedyś, co mówił, że jak zmieni się gcc na g++ to od razu trzeba cały kod przepisać na obiektowy.

Fascynujący przypadek medyczny, ale chyba już tu nie pisze.

To tylko niewiedza. Ja programuję w C++ od lat ~25. Programiści embedded słyszeli o C++ od szwagra kolegi. Nie wszyscy, ale ciągle większość czerpie opinie z absurdalnych źródeł.

Brednia.

Zerowe.

Bzdura. Jesli tylko nie masz firmy z dykty i paździerza, to oba narzędzia już tam masz. W C są tak samo przydatne, jak w C++.

Coding standard, review, lintowanie, unit testy, bazy bugów i masa innych elementów programowania funkcjonuje w firmach od dziesięcioleci.

Idź i zapytaj, czy zyski są niepewne.

Wiele z nich szlag by trafił bez tych narzędzi. Są krytyczne, dla dowolnego języka programowania i komplikacji projektu.

Nie.

Istnieją zewnątrzne bibliteki oferujące taki bajer.

Prawda taka, że w typowym małym embedded posiadanie heapu jest ogólnie nierozsądne, a posiadanie GC jeszcze bardziej. A jak już go masz (heap), to C++ oferuje RIIA a na nim możesz zabudować wyższe poziomy abstrakcji, takie jak poole czy liczenie referencji.

C++ to narzędzie oferujace pewien zakres rozwiązań problemów, ale nie forsuje jakiegoś konkretnego rozwiązania. Java forsuje GC, choć są wersje bez.

Używałem GC w C++ do pewnego specyficznego zagadnienia. Mogę. Ale prawda taka, że większośc softu w C++ stosuje raczej metody zarządzanie heapem typu liczenie referencji albo ownership.

A w małych systemach nic nie stosuje. Bo i użycie malloc/new nie ma tam sensu.

Pominąłeś coś: *semantyka* referencji jest inna.

To oznacza, że w javie:

a = b

i w C++

a = b

oznaczają dwie kompletnie rózne rzeczy. Java przenosi uwspólniony ownership, C/C++ kopiuje. C/C++ preferuje kopie, Java preferuje uwspólnianie właśności.

Java robi to dlatego, że ma Garbage Collector i może.

W C++ jest kopia, bo to zgodne z semantyką C i nie ma w C++ tak naprawdę żadnej pamięci allokowanej dynamicznie - allokacja jest dostarczana przez zewnętrzne bibliteki, wględem samego języka. I może jej nie być, co nie jest niczym dziwnym w embedded.

W javie statyczna allokacja to po prostu statyczny obiekt. Allokowany przy pierwszym użyciu.

Java jest znacznie mniej elastyczna.

W c++ to po prostu to samo co w C, powiększone o klasy, jak komuś potrzebne.

Allokacja w runtime nie jest za darmo: ryzykujesz fragmentację i w ogóle potrzebujesz jakiegoś heapu.

To podstawowy powód średniego nadawania się Javy do embedded, nawet po wycięciu jej z Garbage Collectora, semantyka języka jest mocno niewygodna do obsługi ciasnej pamięci a bezustannie ją preferuje.

Przecięz przed chwilą mówiłeś, że powodem nieużywania C++ jest to, że kolega może coś napisać i bedzie dramat.

Skoro jesteś sam, to te argumenty przestaja mieć sens.

Tak.

Coding standard (jest ich wiele):

formatting link
Review (jest ich wiele, są komercyjne):
formatting link
Linter (darmowych jest mało):
formatting link

Nie. Nic nie kosztuje. Ta wiedza ma wręcz ujemny koszt. Zyskujesz więcej niż tracisz.

Kompilacji i lintowania. Oba wykrywają inne przestrzenie problemów.

To nie jest prawda od bardzo, bardzo dawna.

Typowy kod w C to asembler o sładni klamrowej, gdzie jest pełno void*, intów i ch... wie co jeszcze.

W C++ masz więcej wysokopoziomowych typów i statyczne typowanie.

To dla lintera jest znaczące ułatwienie analizy składni.

Jak masz kB RAM to C++ jak znalazł. Dzięki kilku sztuczkom można sobie prześlicznie i bezpiecznie pisać kod w ciasnym RAM.

To, że wspomniałeś tutaj małą ilośc RAMu oznacza, że komplenie nie rozumiesz czym jest C++.

On niczego nie zmienia w ilosci RAMu ani kodu wynikowego, w większości swoich fajnych funkcji. Prawie całe dobro płynące z C++ to tylko metajęzyk, generujący bezpieczniejszy, a czasami lepszy kod wynikowy.

Jak Ci, co pisali w asemblerze, w "bezpiecznym" Ada i spowodowali spadek Ariane 5?

Fuckup wszędzie jest możliwy.

Popełniasz własnie ten bład, co prawie kązdy embedowiec - nie masz pojęcia jak działa C++ ,więc zakłądasz, że wymaga ogromnych ilosci RAMu, bo tam są obiekty a to prawie jak Java.

Nie wymaga. Generuje ten sam kod co C. ALe pozwala ten kod napisać bezpieczniej, czytelniej, testowalniej. I zje tyle ramu, na ile styknie IQ programisty.

Około 10 sekund na przeczytanie posta na usenecie, że jest std::size zamiast sizeof.

Zyski? Pewnie kilka godzin debugowania teraz i w nastepnych przypadkach.

Mi wychodzi koszt ujemny.

A z jakiego powodu ktoś miałby w ogóle wpaść na to żeby zamieniać sizeof. Trochę naciągnane. jeśli ktoś w ogóle miałby świadomość że w C plus plus jest "lepiej" to używał by tego od samego początku. Žeby mieć taką świadomość użycia to niestety wcześniej musiałby się tego trochę nauczyć. Więc kosz nauki nie jest tutaj zerowy a tym bardziej ujemny.

A może zaczniemy od tego by tak diodami nie migać, co? bo jak ktoś tak miga diodami to później sam sobie tworzy (niesitniejace w innych sposobach) problemy, które później dzielnie musi rozwiązywać niczym socjalizm.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required