Niewłasciwa wartość zmiennej

Niewłasciwa wartość zmiennej
D3
  • Rejestracja:ponad 6 lat
  • Ostatnio:około rok
  • Postów:58
1

Jaka może być przyczyna takiej sytuacji? Jest to kod działający na STM32, więc może jakiś wyciek pamięci w przerwaniu. Chociaż to jednak mało prawdopodobne by w tak krótkim czasie między deklaracją zmiennej single_ack_message_length do breakpoint'u trafiło akurat jakieś przerwanie. Cały kod debugowany przy optymalizacji O1, jedynie ta funkcja ma zmienioną optymalizację w celu dokładniejszej analizy, standard kompilatora GNU11.

Kopiuj
#pragma GCC push_options
#pragma GCC optimize ("O0")
MonitoringParseMessStatus monitoring_ack_message(char *msg, uint16_t length)
{

	MonitoringParseMessStatus res = M_BAD_MESS;
	uint16_t single_ack_message_length = 18; // minimum len
	if(length < single_ack_message_length)
		return M_NAK;

	uint8_t len_mess = strlen(msg);
	char single_message[len_mess + 1];


	while(length >= len_mess && length >= single_ack_message_length)
	{
		memset(&single_message[0], 0, sizeof(single_message));
		memcpy(&single_message[0], msg, single_ack_message_length);

		msg += len_mess + 1;
		length -= len_mess;
		len_mess = strlen(msg);

		char * ack_ptr = strstr(single_message, "\"ACK\"");
		if(ack_ptr == NULL)
		{
			ack_ptr = strstr(single_message, "\"NAK\"");
			if(ack_ptr != NULL)
			{
				return M_NAK;

			}

			res = M_BAD_MESS;
			continue;
		}
		else
			res = M_ACK;

		char *seq_ptr = ack_ptr + strlen("\"ACK\"");
		int seq = atoi(seq_ptr);

		for(int i = 0; i < QUEUE_SIZE; i++)
		{
			if(monitoring_queue[i].set == false)
				continue;

			if(monitoring_queue[i].sequence != seq)
				continue;

			monitoring_queue[i].set = false;
			monitoring_connected_set(monitoring_queue[i].monitoring_num, true);
			monitoring_send_earliest_event();
			break;
		}
	}
	return res;
}
#pragma GCC pop_options

Kiedy zatrzymuję kod na linii uint8_t len_mess = strlen(msg); widze, że wartość single_ack_message_length wynosi 65441

screenshot-20220325112650.png

edytowany 2x, ostatnio: danielbr3
Zobacz pozostały 1 komentarz
D3
dodałem również kod
MarekR22
pełen kontekst. kod całej funkcji i jeszcze podaj ustawienia kompilatora
D3
ok, dodałem. Coś jeszcze moze być przydatne?
RE
a taka głupia rada. Dla mnie to jest jakiś rodzaj stąłej. weź to zrób jako define i niech wstawia po prostu liczbę.
D3
@recovery: zmieniłem typ na static już, to pomaga ale nadal w funkcji pojawia się niezdefiniowane zachowanie. Wstawiłem zdjęcie w ostatniej wiadomości
stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 2 godziny
0

A modyfikujesz gdzies zawartosc tej zmiennej? Nie masz przeciez gwarancji, ze to pierwsza instrukcja po zadeklarowaniu :)


λλλ
D3
@stivens: Niezbyt rozumiem co masz na myśli. Przecież ta zmienna jest tworzona za każdym razem po wywołaniu funkcji na stosie. Funkcja zostaje tutaj wywołana pierwszy raz, bo od razu po zresetowaniu systemu mam ustawionego breakpoint'a. W return wyzej też nie wpada, tam jeszcze wartość jest prawidłowa. Jedynie podejrzenie jakie na razie mam to że z jakiegoś powodu stos zapisywany jest na niedozwolony obszar w pamięci, gdzie zapisywany jest np. jakiś rejestr mikrokontrolera (wartość ta musi być bardzo często zapisywana żeby w tak krótkim czasie doszło do jej nadpisania.
stivens
Ah, sorry. Podales kod w formie obrazka i z jakiegos powodu sobie ubzduralem ze tutaj jest gdzies petla
D3
  • Rejestracja:ponad 6 lat
  • Ostatnio:około rok
  • Postów:58
0

@stivens: Niezbyt rozumiem co masz na myśli. Przecież ta zmienna jest tworzona za każdym razem po wywołaniu funkcji na stosie. Funkcja zostaje tutaj wywołana pierwszy raz, bo od razu po zresetowaniu systemu mam ustawionego breakpoint'a. W return wyzej też nie wpada, tam jeszcze wartość jest prawidłowa.
Jedynie podejrzenie jakie na razie mam to że z jakiegoś powodu stos zapisywany jest na niedozwolony obszar w pamięci, gdzie zapisywany jest np. jakiś rejestr mikrokontrolera (wartość ta musi być bardzo często zapisywana zeby w tak krótkim czasie doszło do jej nadpisania).

katakrowa
  • Rejestracja:około 10 lat
  • Ostatnio:około 2 lata
  • Lokalizacja:Chorzów
  • Postów:1670
2

Debugujesz z włączonymi optymalizacjami czy bez?
Być może kompilator coś zoptymalizował i stąd dziwna wartość.
Podejrzyj co dzieje się w debugerze ale assemblera (o ile środowisko, które używasz to wspiera)


Projektowanie i programowanie. Hobbystycznie elektronika i audio oszołom.
MarekR22
również za mało kodu, jeśli single_ack_message_length jest używana później to powinno pokazywać coś sensownego, jak nie, to as-if rule może skrócić czas życia zmiennej.
D3
dodałem informację w pytaniu
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:9 minut
0

Uzupełniłem braki i mam coś takiego: https://godbolt.org/z/rq54GseK8

Na razie nie widzę wyjaśnienia, czemu niby debugger pokazuje złą wartość.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
D3
Nie winiłbym tutaj tylko debuggera. Program zawiesza się również w normalnym trybie pracy, bez debugowania. Zawiesza w linii 18 co jest oczywistą konsekwencją. Instrukcje z assemblera byłyby w czymś pomocne? Sam niezbyt je rozumiem
several
  • Rejestracja:ponad 15 lat
  • Ostatnio:3 minuty
1

Co się stanie jeśli single_ack_message_length zdefiniujesz jako const albo #define?

Kopiuj
const uint16_t single_ack_message_length = 18;
// ..........
#define single_ack_message_length 18

D3
Z const wyglada to dokładnie tak samo, definicji nie sprawdzałem i aktualnie testuję jeszcze ze słowem static
several
Komentarze są do offtopu. Do odpowiedzi na temat służą normalne odpowiedzie, dzięki temu odpowiedź będzie lepiej widoczna dla innych urzytkowników.
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:9 minut
0

@danielbr3:
Podaj kompilator i jego ustawienia.
Czy na pewno w kodzie masz

Kopiuj
#pragma GCC push_options
#pragma GCC optimize ("O0")

czy dodałeś to na wyrost?

Gdyby były jakieś optymalizację to można wyjaśnić czemu debuger cię kłamie. Z wymuszonym -O0 to nie rozumie skąd ten problem.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
D3
Dodałem to zeby móc podglądać wszystkie zmienne, inaczej na optymalizacji O1 nie byłem w stanie wszystkiego sprawdzać przy debugowaniu. No i problem nie dotyczy wyłącznie debugowania. Przy normalnym działaniu program też się zawiesza
D3
@MarekR22: jakie konkretnie ustawienia kompilatora moga się przydać. Znalazłem takie opcje: -mcpu=cortex-m4 -std=gnu11 -DUSE_HAL_DRIVER -DRELEASE -DSTM32G474xx -c -I../Core/Inc -I../USB_Device/App -I../USB_Device/Target -I../Drivers/STM32G4xx_HAL_Driver/Inc -I../Drivers/STM32G4xx_HAL_Driver/Inc/Legacy -I../Middlewares/ST/STM32_USB_Device_Library/Core/Inc -I../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc -I../Drivers/CMSIS/Device/ST/STM32G4xx/Include -I../Drivers/CMSIS/Include -O1 -ffunction-sections -fdata-sections -Wall -fstack-usage --specs=nano.specs -mfpu=fpv
D3
  • Rejestracja:ponad 6 lat
  • Ostatnio:około rok
  • Postów:58
0

Udało mi się jeszcze coś takiego złapać jak zmieniłem typ tej zmiennej single_ack_message_length na static żeby już ona zaczęła działać. To tez wygląda trochę dziwnie. Sorry że na zdjęciu ale ciężko byłoby to inaczej pokazać

screenshot-20220325131448.png

RE
a jesteś w ogóle pewien że strln zwraca uint8? to jest size_t jaki jest on na stm32? Dawno nie siedziałem na stm32 to nie pamiętam.
RE
Teraz sobie coś z stm32 powoli przypominam. Kiedyś przez przypadek wyjechałem po za tablicę, i zmieniałem wartosci innych zmiennych. Może gdzieś tak jest gdzieś w kodzie u ciebie? Static to inne miejsce w pamięci jak pamiętam(?).
AL
@revcorey: tak static to inna sekcja, a na pewno nie stos ;)
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:9 minut
0
danielbr3 napisał(a):

Udało mi się jeszcze coś takiego złapać jak zmieniłem typ tej zmiennej single_ack_message_length na static żeby już ona zaczęła działać.

Programowanie permutacyjne jest BARDZO ZŁĄ PRAKTYKĄ!


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:9 minut
3

Chwila chwila, teraz pojechałeś debugerem dalej i to poniżej miejsca gdzie masz undefined behavior z buffer overflow, ukryte w ciekawy sposób.

Na dodatek z tego co widzę z ostatniego screenshota msg zawiera dane binarne, a ty robisz na nich strlen!
I masz jeszcze argument, który sugeruje, że rozmiar wiadomości jest zero, ale ty mimo wszystko używasz strlen.
strlen na czymś co nie jest napisem zakończonym zerem to kolejne UB.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 3x, ostatnio: MarekR22
D3
o którym argumencie mówisz, że sugeruje zero? Kod nie jest pisany przeze mnie i zaraz się zabiorę za poprawianie tych niebezpiecznych miejsc, jednak nie widzę do końca powiazania z tymi sytuacjami, które zaobserwowałem. Same wiadomosci podawane do funkcji są podawane bezpośrednio z komunikacji przychodzącej od innego urządzenia, ale jak na razie nie zauważyłem żeby jakakolwiek wiadomość nie miała NULLa na końcu
RE
  • Rejestracja:ponad 18 lat
  • Ostatnio:około 8 godzin
2

Po komentarzach MarkR22 się przypatrzyłem się wyraźniej niż rzu okiem i faktycznie tu UB nie w jednym miejscu.
Proponuję do takiej funkcji podejść inaczej. Zrób unit testy. To C i stm32 więc może spróbuj czegoś takiego
http://www.throwtheswitch.org/unity
Napisz tą funkcję używając UT najpierw. łatwiej ci to będzie sprawdzać. Później wleź tym na stm32. Zauważ ta funkcja operuje w zasadzie na czystym C a nie na jakiś mambo jambo z stm32 więc powinno to być łatwe do przetestowania.


We are the 4p. Existence, as you know it, is over. We will add your biological and technological distinctiveness to our own. Resistance is futile
AL
  • Rejestracja:prawie 11 lat
  • Ostatnio:prawie 3 lata
  • Postów:1493
0

Wygląda wstępnie, że gdzieś wyjeżdzasz poza zakres. Dalej mi się analizować nie chce za bardzo ;)
zobacz z włączonym sanitizerem: https://godbolt.org/z/o86W5TTPb

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)