Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 28 mar 2024, o 09:52


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 12 ] 
Autor Wiadomość
PostNapisane: 19 gru 2018, o 14:32 
Offline
Nowy

Dołączył(a): 27 lis 2018
Posty: 5
Pomógł: 0

Witam.

Napotkałem na nietypowy problem. Otóż opracowuję sobie pewien programik pomagający przeliczać stany urządzenia sterowanego AVRem. Program na PC.
Posiadam zadeklarowaną i uzupełnioną zerami tablicę znaków:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Kolejno obliczają się dane, które mają być zapisane do tablicy_1 oraz alternatywne dane zapisywane do tablicy_2.
Kolejno mam funkcję, która brzmi mniej więcej tak:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


No i ok. Powstają mi dwa ładnie wygenerowane bufory główne i alternatywne.
Do tablicy tablica_1 wklejany jest bufor główny, do tablicy tablica_2 wklejany jest bufor alternatywny.

Kolejno w programie pobieram sobie kolejny wyraz z tablic i wykonują się dwie pętle na tablicy_1 i tablicy_2.
Niezależnie od tego w jakiej kolejności zapisuję tablice i odczytuję tablice, zawsze w drugiej pętli gubiony jest pierwszy wyraz tablicy.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Adresy sprawdzane przez "%p" przekazywanych zmiennych się zgadzają, rozmiary tablic się zgadzają, zapisywane dane są "debugowane" i wyświetlane przed zapisem do tablic.
Typy danych zgodne z typem tablic. Przewidziany zakres miejsca w przypadku char i /0. No i tyle mi przychodzi do głowy...

Czy jest szansa na jakąś sugestię tej zagadki?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 gru 2018, o 14:53 
Offline
Nowy

Dołączył(a): 27 lis 2018
Posty: 5
Pomógł: 0

Program na PC, więc int, uint, bez znaczenia. To jest taki program pomocniczy dla mnie. AVRa samego się nie czepiamy, bo tu jest ok.
Postaram się jeszcze ten opis skrócić, jak wygląda wypluwanie wyników w pętli.
Załóżmy, że przeszliśmy etap wypełnienia pętli. I dla uproszczenia wyniki:
1 wykonanie pętli for dla tablicy tablica_1:
i = 0 -> wartość = 1;
i = 1 -> wartość = 2;
i = 2 -> wartość = 3;
i = n -> wartość = k;
To samo i tak samo z tablicą wartości alternatywnych tablica_2.
Wyplute prawidłowo wartości z pętli są przeliczane.
I potrzebne ponowne wykonanie pętli. No to jedziemy:
tablica_1:
i = 0 -> wartość = 1;
i = 1 -> wartość = 2;
i = 2 -> wartość = 3;
i = n -> wartość = k;
No i jest wszystko ok.
Teraz druga tablica:
tablica_2 (wartości alterantywne):
i = 0 -> wartość = NULL; (tylko tutaj jest problem)
i = 1 -> wartość = 2; a dalej wypisuje prawidłowo do ostatniej wartości.
i = 2 -> wartość = 3;
i = n -> wartość = k;

No i zonk.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 gru 2018, o 16:39 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 04 lut 2014
Posty: 164
Pomógł: 3

Ciekawa zagadka. Cały listing kodu byłby lepszy do analizy. Tak czy siak podejrzewałbym albo nie wpisanie wartości do tablicy lub nadpisanie tablicy nr 2 ponieważ C (może i C++) czasami optymalizuje dostęp do komórek pamięci umieszczając jedną tablicę zaraz za drugą. Wartość NULL świadczyłaby o tym że gdzieś tutaj jest problem bo inaczej byłaby jakaś wartość a tak nie jest.
Sprawdź czy tak jest - tzn wyświetl sobie adresy tablicy 1 i tablicy 2. Jeżeli tak jest to zmniejsz tablicę 1 i sprawdź efekt.

:edit - napisane na szybko:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

_________________
::::::: C ::::::::::
:::::: C++ :::::::::



Ostatnio edytowano 19 gru 2018, o 17:14 przez Lex_, łącznie edytowano 3 razy

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 gru 2018, o 16:53 
Offline
Nowy

Dołączył(a): 27 lis 2018
Posty: 5
Pomógł: 0

Miałem już próbować wykonać podana wyżej propozycję, ale z ciekawości chciałem wykonać kompilację na innej platformie systemowej.
Ponieważ nie mam aktualnie dostępu do własnego komputera, do takich celów mam w swoim telefonie zainstalowany emulator z Arch Linux for amr i zainstalowanym gcc. Wykonałem kompilację i uwaga... Działa...
Do tej pory wykonywałem kompilacje na Windowsie.
Do kompilowania zaprzęgnięte mingw w Code Blocks.
Czyli co? Coś jest źle napisane i mam zmieniać logikę, czy kompilator w windowsie ma problem?
Podejrzewam, że gdyby coś z adresami było nie tak, to byłby ten sam efekt i w linuksie.
Postaram się mimo wszystko późnym wieczorem lub w dniu jutrzejszym przyjrzeć jakie tam adresy latają, bo na Windowsie też musi działać.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 gru 2018, o 16:55 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 04 lut 2014
Posty: 164
Pomógł: 3

Mingw to GCC więc jest to dziwne. Ale jak będziesz miał możliwość to sprawdź bo ciekawy przypadek.

_________________
::::::: C ::::::::::
:::::: C++ :::::::::



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 gru 2018, o 17:47 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

Palvanen napisał(a):
Witam.

Napotkałem na nietypowy problem. Otóż opracowuję sobie pewien programik pomagający przeliczać stany urządzenia sterowanego AVRem. Program na PC.
Posiadam zadeklarowaną i uzupełnioną zerami tablicę znaków:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Czemu uważasz, że masz dwie tablice wypełnione zerami?
Wg mnie masz tablice z pierwszym elementem równym 0, a reszta to losowe dane.
A może ta definicja tablicy to skrót myślowy?
No chyba, że te tablice są globalne albo static. To niestety nie wynika z kodu, który podałeś.
Jeśli są globalne lub static to oczywiście nie musisz ich wypełniać zerami, bo zrobi to za Ciebie kompilator.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 gru 2018, o 18:57 
Offline
Nowy

Dołączył(a): 27 lis 2018
Posty: 5
Pomógł: 0

Do przedmówcy:
Skrót myślowy. 0x0 to nawet nie 0, ponieważ żeby to było lepiej widoczne, powinno być 0x30 i wtedy by było "zero". Ale ok. Wprowadziłem w błąd tym zapisem. Jak to mówią, za dużo myśli na sekundę ;)
W każdym razie na 100% tablice są wypełnione zerami.
No i teraz poszedłem wg poprzedniego zalecenia i prześledziłem adresy, oraz co w nich siedzi. Okroiłem rozmiar obu tablic do 4 parametrów.
Wykonałem kompilację tego kodu na Windowsie i w linuksie, tym razem w wersji desktopowej linuksa.
Załączam dwa obrazki. Jak widać w wynikach linuksowych zawartości tablic się zgadzają.
Natomiast w wersji windowsowej teraz wydarzyło się jeszcze co innego. Nie tyle pierwsza wartość została skasowana, co zostały zmienione dwie środkowe wartości. Teraz tym bardziej nie mogę ogarnąć co to może powodować. Zaznaczam, że druga tablica może mieć w obu przypadkach inne wartości po każdym wywowałniu, ponieważ są to wartości alternatywne. Najważniejsze, żeby w każdym wywowałaniu dane poszczególnej tablicy się powtarzały.

Coraz bardziej jednak dochodzę do wniosku, że muszę mieć coś skopane w kodzie pod względem logiki, ponieważ nie powtórzył się w identyczny sposób problem przedstawiony przeze mnie w pierwszym poście. Tylko jakimś dziwnym trafem linuks to ogarnia...

ObrazekObrazek



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 gru 2018, o 20:04 
Offline
Nowy

Dołączył(a): 27 lis 2018
Posty: 5
Pomógł: 0

Z tymi strukturami to pewnie by było dobre rozwiązanie tylko sęk w tym, że w przypadku zależności rozpisanych na 2,1k linii kodu ciężko to teraz uaktualnić. Ale w momencie jak pisałem o tym 0x30 dla zera (ze względu na typ char) przyszedł mi do głowy pewien pomysł.
Polegał on na tym, aby zamiast od razu ładować chary do tablicy, zmienić typy tablic na int i do tablic pakować faktycznie przeliczone dane liczbowe odpowiadające znakom tablicy ASCII. I dopiero to przerabiać w drugiej kolejności na char.
Napisałem taką protezę do funkcji, która oprócz przeliczania do dwóch tablic powołuje jeszcze jedną tablicę (dodatkowa tablica, bo powstała proteza) gdzie przekształca to co przeliczyła z intów na chary. I dopiero to wypluwane jest na ekran.
No i noga chudego bociana, jak ręką odjął.
Być może faktycznie gdzieś w obliczeniach dzieje się coś dziwnego, co powoduje, że chce upakować do tablicy chara, którego nie potrafi zidentyfikować, może jakieś kodowanie znaków ma coś wspólnego - niby proste ASCII...

Jakie wnioski? Hmm... Jak narazie to chyba takie, że jak dużo złożonych rzeczy się robi i chce się uzyskać prawidłowy program na Windows/Linux jednocześnie, to lepiej jechać na liczbach. A jak chcemy mieć znaki, to dopiero później bawić się w konwersje.
Język C naprawdę jest pełen niespodzianek.

Dziękuję serdecznie wszystkim za pomoc i być może będzie kiedyś okazja, aby i mi udało się w czymś pomóc.
Ale mimo wszystko oby kodzenie szło każdemu tak, żeby tych problemów było jak najmniej.

Jeśli ktoś jakąś opinią chciałby się podzielić, to chętnie bym poczytał. A jak nie, to temat do zamknięcia?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 gru 2018, o 23:43 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 04 lut 2014
Posty: 164
Pomógł: 3

Konwersji dokonujesz przez rzutowanie typów ? Coś musiało być zamieszane, być może mieszały się typy.
Z czystej ciekawości napisałem sobie coś takiego:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Różne typy i różne wartości. A tutaj wyniki - raczej zaskoczenia dużego brak:
Obrazek

W ostatnim wypadku jedynie pokusiłem się o rzutowanie inta na typ char tak już nieco fantazyjnie :)
Typ int ma conajmniej 2 bajty więc od razu tablica się rozrasta, choć potem i tak skracasz to do 1 bajta (typ char). Elastyczność typów to czasami miecz obosieczny w C.
Ciekawe jednak, że program pod windowsem się wykrzaczał a linuxem sobie radził.

Pozdrawiam.

_________________
::::::: C ::::::::::
:::::: C++ :::::::::



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 20 gru 2018, o 09:13 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

Nie gniewajcie się koledzy, ale trochę mi to przypomina wykłady profesora "mniemanologii stosowanej" ;) Trudno jest rozważać błędy w kodzie, którego się nie widziało na oczy. Ja rozumiem, że przedstawienie do analizy na forum kodu zawierającego tysiące linii nie jest dobrą praktyką, ale zawsze można wydzielić problem do osobnego projektu, ograniczając kod do minimum, przy którym jeszcze błąd występuje.

Skoro już jednak próbujemy zgadnąć przyczynę problemu, to chciałbym zwrócić uwagę na pewien fakt. Standard C definiuje różne podstawowe typy danych:
  • char
  • signed char
  • unsigned char
To czy liczba jest ze znakiem, czy bez znaku, ma dla kompilatora kluczowe znaczenie przy doborze odpowiednich instrukcji asm.
To czy typ char zostanie potraktowany jako signed czy unsigned jest "machine dependent", ale może też być wymuszone przez opcje kompilatora -fsigned-char i -funsigned-char. Dobrą praktyką, szczególnie w przypadku pisania kodu, który ma być przenośny, jest jawne oreślenie "signedness" typu char, czyli deklarowanie zmiennych zawsze jako signed char lub jako unsigned char.

Bez kodu nie wiadomo, jakie operacje są wykonywane na elementach tablicy, więc to tylko zgadywanka, ale spróbowałbym zadeklarować jawnie typ char jako signed lub unsigned.

Sądząc po tej wypowiedzi:
Palvanen napisał(a):
...przyszedł mi do głowy pewien pomysł.
Polegał on na tym, aby zamiast od razu ładować chary do tablicy, zmienić typy tablic na int i do tablic pakować faktycznie przeliczone dane liczbowe odpowiadające znakom tablicy ASCII. I dopiero to przerabiać w drugiej kolejności na char.
Napisałem taką protezę do funkcji, która oprócz przeliczania do dwóch tablic powołuje jeszcze jedną tablicę (dodatkowa tablica, bo powstała proteza) gdzie przekształca to co przeliczyła z intów na chary. I dopiero to wypluwane jest na ekran.
No i noga chudego bociana, jak ręką odjął.
coś może "być na rzeczy" ;)

EDIT:
To jeszcze bardziej przemawia za moją teorią:
Palvanen napisał(a):
z ciekawości chciałem wykonać kompilację na innej platformie systemowej.
Ponieważ nie mam aktualnie dostępu do własnego komputera, do takich celów mam w swoim telefonie zainstalowany emulator z Arch Linux for amr i zainstalowanym gcc. Wykonałem kompilację i uwaga... Działa...

W kodzie dla x86 typ char jest zwykle traktowany jako signed char, a na platformę ARM - jako unsigned char.



Ostatnio edytowano 20 gru 2018, o 10:12 przez andrews, łącznie edytowano 1 raz

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 20 gru 2018, o 10:08 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

andrews napisał(a):
Nie gniewajcie się koledzy, ale trochę mi to przypomina wykłady profesora "mniemanologii stosowanej" Trudno jest rozważać błędy w kodzie, którego się nie widziało na oczy. Ja rozumiem, że przedstawienie do analizy na forum kodu zawierającego tysiące linii nie jest dobrą praktyką, ale zawsze można wydzielić problem do osobnego projektu, ograniczając kod do minimum, przy którym jeszcze błąd występuje.

Nic dodać, nic ująć ;) ... dlatego ja nie włączałem się nawet (niestety) do tej dyskusji ... bo tak można sobie właśnie ... pisać, pisać zgadywać, wróżyć, gadać ... ot taka pogaducha ;)

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 23 gru 2018, o 09:19 
Offline
Użytkownik

Dołączył(a): 26 cze 2016
Posty: 186
Pomógł: 7

Spróbuj wyłączyć wszelkie optymalizacje kompilatora, góra -O2 , może coś z tym jest.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 12 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 0 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO