kategoria: ANSI C
[#1] [C] - Porownanie danych nie dziala.
Ostatnio robiac testy dzialania programu do zapisywania danych do pamieci
odkrylem ze procedura weryfikujaca nie dziala. Oto fragment kodu:
#define ADRES_START  0x00f00000
#define BYTES_LENGHT 0x00040000

adres = 0;

for(x=ADRES_START; x<ADRES_START+BYTES_LENGHT; x++)
{
          *(UBYTE*)(x) = Dane[adres];

           if(Dane[adres] != *(UBYTE*)(x))
           {
                        printf("Zapis bledny, adres=$%x\n", x);
                        fail = 1;
                        break;
           }
                                
           adres++;
}


To ku mojemu zdziwieniu okazalo sie ze weryfikacja nie dziala.
Jesli obszar pamieci nie istnieje to weryfikacja i tak przejdzie poprawnie.
Z ciekawosci zdeasemblowalem ten fragment kodu i wyglad to tak:

| 00A8  2C3C 00F0 0000                 MOVE.L      #00F00000,D6
| 00AE  2079  0000 0004-02             MOVEA.L     02.00000004,A0
| 00B4  D1C7                           ADDA.L      D7,A0
| 00B6  1010                           MOVE.B      (A0),D0
| 00B8  2246                           MOVEA.L     D6,A1
| 00BA  1280                           MOVE.B      D0,(A1)
| 00BC  1210                           MOVE.B      (A0),D1
| 00BE  B200                           CMP.B       D0,D1
| 00C0  6714                           BEQ.B       00D6
| 00C2  2F06                           MOVE.L      D6,-(A7)
| 00C4  4879  0000 008C-01.2           PEA         01.0000008C
| 00CA  4EB9  0000 0000-XX             JSR         _printf
| 00D0  504F                           ADDQ.W      #8,A7
| 00D2  7A01                           MOVEQ       #01,D5
| 00D4  600C                           BRA.B       00E2
| 00D6  5287                           ADDQ.L      #1,D7
| 00D8  5286                           ADDQ.L      #1,D6
| 00DA  0C86 00F4 0000                 CMPI.L      #00F40000,D6
| 00E0  6DCC                           BLT.B       00AE
| 00E2  4A05                           TST.B       D5
| 00E4  660E                           BNE.B       00F4


Wg mnie to nie ma prawa dzialac. Pytanie czy cos robie zle i jak to moge obejsc?
[#2] Re: [C] - Porownanie danych nie dziala.

@Phibrizzo, post #1

W jakich warunkach robisz ten test?

Nie wiem czym jest dokładnie miejsce w którym pamięć nie istnieje, ale w zależności od rozwiązań sprzętowych, odczyt wartości zapisanej z nieistniejącego obszaru jest możliwy dzięki pojemności ścieżek kiedy coś znajduje się za jakimiś buforami lub w przypadku pamięci cache, gdzie program wykonuje się w pętli, a jedynymi cyklami dostępu do szyny są zapisy i odczyty danych, wtedy odczytasz daną z ścieżek, które przed chwilą rozładowałeś/naładowałeś.

Gdybyś robił test poprzez dwa kolejne zapisy i dwa odczyty, to mógłbyś tego problemu uniknąć.
[#3] Re: [C] - Porownanie danych nie dziala.

@WyciorX, post #2

CDTV z 68010 (realna, nie UEA).
Na poczatku tez myslalem ze to przez cache bo ponoc 010 jakis tam posiada (informacje sprzeczne)
Jednak deasemblacja mowi cos innego.

Faktycznie sprobuje zapisywac to w inny sposob.
[wyróżniony] [#4] Re: [C] - Porownanie danych nie dziala.

@Phibrizzo, post #1

To ku mojemu zdziwieniu okazalo sie ze weryfikacja nie dziala.


Dlaczego sie zdziwiłes? Weryfikacja jest tak napisana ze moje działać ale nie musi.

Pytanie czy cos robie zle i jak to moge obejsc?


Tak, robisz to zle. Zalozyles ze kompilator jest marnej jakości (twoj kod być moze działa poprawnie przy kompilacji bez optymalizacji, -O0) a on okazał sie lepszy niz myślisz.

Język C w żadnym miejscu standardu nie mówi ze dostęp do adresu jest weryfikowany w jakikolwiek sposób a adres musi być poprawny. W twoim wypadku adres jest niedostępny, ale spojz na to co robisz. Tak w uproszczeniu:

B = A;
    if (A != B) { .... }


Zaraz po przypisaniu do B wartości A porównujesz czy A i B sa takie same. Kompilator to zoptymalizowal i stwierdził ze wyrażenie (A != B) jest zawsze fałszywe.

Co możesz zrobić? Możesz powiedzieć kompilatorowi ze dostęp do zmiennej pod podanym adresem musi być zawsze zrealizowany. Użyj w tym celu słowa kluczowego volatile:

*(volatile UBYTE*)(x) = Dane[adres];
        if(Dane[adres] != *(volatile UBYTE*)(x))


To słowo kluczowe nie pozwoli kompilatorowi na optymalizacje dostępu do zmiennej i zaraz po zapisie do pamięci (pierwsza linijka) pojawi sie odczyt z pamięci (druga linijka).

Ostatnia aktualizacja: 02.07.2020 17:51:29 przez mschulz
[#5] Re: [C] - Porownanie danych nie dziala.

@WyciorX, post #2

Gdybyś robił test poprzez dwa kolejne zapisy i dwa odczyty, to mógłbyś tego problemu uniknąć.


W skrocie: NIE.

DLuszsze wyjasnienie: Kompilator skróci następujący kod:

*(UBYTE*)b = a;
*(UBYTE*)b = a;
*(UBYTE*)b = a;
*(UBYTE*)b = a;


do jednego zapisu. Tylko jednego. Chyba, ze użyje sie słowa kluczowego volatile.

Ostatnia aktualizacja: 02.07.2020 17:51:42 przez mschulz
[#6] Re: [C] - Porownanie danych nie dziala.

@mschulz, post #4

Użyj w tym celu słowa kluczowego volatile

Faktycznie pomoglo. Dzieki :)
[#7] Re: [C] - Porownanie danych nie dziala.

@mschulz, post #5

Pisałem akurat do kontekstu zapisu danych od strony sprzętowej, dla przykładu, jeśli jakaś pamięć znajduje się za buforem i tą pamięć usuniesz, to algorytm testujący typu zapisz bajt-odczytaj bajt nie wykaże błędów tak długo jak wielkość zapisywanych danych jest mniejsza, lub równa szerokości szyny, ścieżki potrafią trzymać ładunek przez kilka-kilkanaście sekund. Innym znanym mi przypadkiem jest algorytm wykrywania pamięci SLOW, jeśli masz tej pamięci 1.5MB, a procesor posiada cache instrukcji lub jest on odizolowany od szyny Amigi i kickstart jest załadowany do fastu, to zostanie wykryte 1.8MB pamięci SLOW, właśnie z powodu algorytmu zapisz bajt-odczytaj bajt i trzymaniu ładunku przez ścieżki.
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem