Delphi - problem z pamięcią?

0

Cześć, mam zdaje się problem z pamięcią. Prosty fragment kodu, który sam z siebie nie może powodować błędów(i nota bene nie powoduje). Błędy pojawiają się w momencie sprawdzenia warunku if, lub wywołania funkcji, bo debugger do funkcji nie wchodzi.

Wynalazłem coś takiego.
Posprawdzałem sobie adresy dwóch zmiennych(obydwie zmienne typu integer) i wyszło mi tak:

zm1: $12EC40, gdy do tego dodać 8 bajtów(32 bity) to wychodzi: $12EC48
zm2: $12EC3C, +8 bajtów = $12EC44, a więc wchodzi w zakres zm1.
Dobrze rozumuję?

Czemu coś takiego się dzieje(zmienne są alokowanie normalnie statycznie) i jak temu zapobiec?

0

Przeca 32 bity to 4 bajty ;>

0
brodny napisał(a)

Przeca 32 bity to 4 bajty ;>

Szlag, faktycznie. Widocznie w nawale próbowałem znaleźć cokolwiek ;)
Anyway kiedy taka sytuacja jak u mnie(AV przy ifie lub wywołaniu funkcji) może wystąpić?
Kod z punktu widzenia algorytmu jest ok.

0

A tak głupio spytam, gdzie tu "nietuzinkowość"? Wątek nie nadaje się nawet na dział Delphi tylko na Newbe, a wylądował w "nietuzinkowe tematy".

0

Może wrzuć problematyczny fragment kodu, ew. osadzony w nieco większym kontekście? Z tego co mi wiadomo, nikt z tego forum nie ma jeszcze licencji wróżki :)

0
brodny napisał(a)

Może wrzuć problematyczny fragment kodu, ew. osadzony w nieco większym kontekście? Z tego co mi wiadomo, nikt z tego forum nie ma jeszcze licencji wróżki :)

Szkoda, bo tu by się przydała ;) Kod jest dobry(umieszczę go za jakieś 1,5 godziny). Najpierw myślałem, że to kwestia tablicy dynamicznych(bo wiem, że Delphi 2005 ma czasem problemy z tymi tablicami), więc przerobiłem na TStringList, ale nic się nie poprawiło.

0

OK, pokazuję kod.

Oto moja problematyczna funkcja(ona jest wywoływana z innej formy, ale tamta raczej nie ma znaczenia).
Żeby była jasność - stringListę tworzę w formie, która wywołuje tą funkcję.

Jest fo funkcja przeciążona

function FindReaders(IP: string; DeviceCount: integer; var IDs: TStringList): integer;
var
  am: boolean;
  pr: integer; //zmienn pr i am potrzebne do wywołania funkcji z SDK
  id: integer; //id
  e: integer; //błąd
  i: integer; //aktualna iteracja
  found: integer; //ilość znalezionych urządzeń
begin
  found:=0;
  IDs.Clear;

  i:=0;
  //deviceCount to ilość urządzeń do znalezienia
  while (found<DeviceCount) and (i<DeviceCount*10) do  //*1
   begin
     e:=UF_SearchModuleBySocket(PChar(IP), 1470, am, pr, id); //szukanie urządzenia - funkcja z SDK
     if e = 0 then
     begin
       if not isValueInList(intToStr(id), IDs) then //to jest moment wywalenia: *2
       begin
         found:=found+1;
         IDs.Add(intToStr(id))
       end;
     end;
     i:=i+1;
   end;

   result:=found;
end;

OK, mały opis:
Miejsce: 1
Najpierw była dodatkowa zmienna o nazwie MaxIterate typu integer.
MaxIterate na począku funkcji dostawało przyrównanie: DeviceCount
10 i było umieszczone w drugim nawiasie (i<MaxIterate). Jednak z niewiadomego mi powodu ta zmienna zerowała się po wykonaniu funkcji z SDK(zmieniłem nazwę i było to samo). Więc postanowiłem wpisać na sztywno tak jak teraz i zaczęło się wywalać a AV w miejscu *2.

Najbardziej mnie denerwuje miejsce wywalenia. Debugger nawet nie wchodzi do funkcji isValueInList.

Co tu jest nie tak albo co można poprawić, żeby to w końcu zaczęło działać?
Zaznaczę, że tą funkcję z SDK wykorzystuję jeszcze w innym miejscu i tam nie ma problemów, więc podejrzewam, że to nie jest kwestia tej fukcji.

[DOPISANE]
Po pierwsze ile zajmuje zmienna string? Tyle, ile ma długości, prawda? Więc sizeof(IP) zwróciło mi 4, gdzie IP = '192.168.1.227', a więc po mojemu powinno być 13.
Po drugie, znalazłem pewną rzecz. Otóż okazało się, że zmienna DeviceCount ma ten sam adres co zmienna i, krótko mówiąc: @DeviceCount = @i.

0

string zajmuje 4 bajty na wskaźnik + 4 bajty długości + długość.
sizeof zwraca 4, bo to wskaźnik. długość stringa dostaniesz przez length.
to shortstring (stary string z tp) zachowuje się tak, jak myślisz.

wywala się? zatrzymaj debuger na linii, która rzuca wyjątkiem, i zobacz jakie wartości wędrują do funkcji.

czemu masz pętlę do 10*DeviceCount? 10 prób wykrycia jednego modułu? czy na jednym porcie może być w ogóle więcej niż jeden moduł?

@DeviceCount = @i - niemożliwe; żadna ze zmiennych nie jest wskaźnikiem, więc nawet jeśli coś maże po pamięci (co jest tu całkiem prawdopodobne, sądząc po opisanych objawach), to nie jest w stanie zmienić adresu ustalonego przez kompilator!

0
ŁF napisał(a)

wywala się? zatrzymaj debuger na linii, która rzuca wyjątkiem, i zobacz jakie wartości wędrują do funkcji.

Zmieniłem całą funkcję na wskaźniki. I generalnie mam wrażenie, że debugger swoje, a aplikacja swoje. Teraz dwie zmienne otrzymują ten sam adres w funkcji, która wywołuje tą.

Natomiast w debugerze wartość DeviceCount(tak naprawdę teraz jest to wskaźnik, ale dla uproszczenia przyjmijmy, że zmienna; mówiąc wartość mam na myśli: DeviceCount^) na samym początku funkcji jest taka, jaka powinna być. Zmienia się ona nagle na losową wartość integer przy wykonaniu pierwszej linii kodu w funkcji. Natomiast z zachowania pętli wynika to, że nadal trzyma wartość, która powinna być, chociaż debugger pokazuje inaczej :|

czemu masz pętlę do 10*DeviceCount? 10 prób wykrycia jednego modułu? czy na jednym porcie może być w ogóle więcej niż jeden moduł?

Tak, modułów na jednym IP standardowo może być 2. Natomiast z użyciem pewnego konwertera, ta ilość rośnie. Natomiast funkcja z SDK(nawet przy standardowym ustawieniu) odszukuje raz jeden moduł, raz inny, dlatego tak to wygląda.

@DeviceCount = @i - niemożliwe; żadna ze zmiennych nie jest wskaźnikiem, więc nawet jeśli coś maże po pamięci (co jest tu całkiem prawdopodobne, sądząc po opisanych objawach), to nie jest w stanie zmienić adresu ustalonego przez kompilator!

Ale tak jest według kompilatora. Tak pokazuje watchList i evaluate window.

0

nie pytałem o jeden IP. pytałem o jeden port, a z tego co widzę funkcja dostaje za każdym wywołaniem w pętli te same parametry, wiec czemu miałaby zwrócić coś innego? port jest zawsze ten sam, 1470.

co do reszty - omg! masz gdzieś paskudny wyciek pamięci, albo własnie znalazłeś błąd w delphi.

0
ŁF napisał(a)

nie pytałem o jeden IP. pytałem o jeden port, a z tego co widzę funkcja dostaje za każdym wywołaniem w pętli te same parametry, wiec czemu miałaby zwrócić coś innego? port jest zawsze ten sam, 1470.

Aha, chodzi o to, że konkretny typ urządzeń działa na konkretnym porcie, który można zmienić. W tym wypadku nie łączę się bezpośrednio z urządzeniem, tylko(w standardowej konfiguracji) ze specjalnym konwerterem(który jest tylko jeden na danym IP). Ot, taka koreańska myśl :D

Zresztą urządzeń może być w jednej firmie nawet i 1000.

co do reszty - omg! masz gdzieś paskudny wyciek pamięci, albo własnie znalazłeś błąd w delphi.

A jak to sprawdzić? Tylko mów jak krowie na granicy. Assemblera nie znam, a programów do znajdowania wycieków jeszcze nigdy nie obsługiwałem. Raz próbowałem, ale nic z tego nie wyszło ;)

0

skrót myślowy - to nie do końca wyciek pamięci, tylko być może któryś kawałek kodu działa nie na własnym kawałku pamięci, znalezienie winnego kodu to ciężka sprawa. masz włączone range checking, buffer overflow i resztę dupereli od debugu w konfiguracji projektu?

0
ŁF napisał(a)

skrót myślowy - to nie do końca wyciek pamięci, tylko być może któryś kawałek kodu działa nie na własnym kawałku pamięci, znalezienie winnego kodu to ciężka sprawa. masz włączone range checking, buffer overflow i resztę dupereli od debugu w konfiguracji projektu?

Teraz włączyłem. Ale build nie zwrócił nic nowego. Nie wiem, czy to podczas buildu powinno coś wypluć, czy kiedy?

0

nie. w trakcie działania... zresztą użyj F1, dowiesz się co w ogóle włączyłeś.

1 użytkowników online, w tym zalogowanych: 0, gości: 1