eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.comp.programming › Bezpieczne przekazywanie ciągów znaków
Ilość wypowiedzi w tym wątku: 5

  • 1. Data: 2010-02-10 20:07:20
    Temat: Bezpieczne przekazywanie ciągów znaków
    Od: "Wojciech \"Spook\" Sura" <s...@s...op.pl>

    Witam!

    Piszę aplikację, która z założenia ma oferować otwartą architekturę pluginów
    skonstruowaną w taki sposób, by owe pluginy można było oprogramowywać w
    dowolnym języku.

    Projektuję teraz interface'y dla pluginów i natrafiłem na niewielką
    zagwózdkę w postaci przekazywania ciągów znaków. Piszę w Delphi, ale
    oczywiście string ani przez myśl mi nie przeszedł - skorzystam na pewno z
    PChara (czyli char*). Problem polega na tym, że potrzebuję od plugina dostać
    kilka informacji w postaci ciągu znaków, a PChara trzeba przecież gdzieś
    zaalokować i gdzieś zwolnić.

    WinAPI ma to ciekawie rozwiązane - zrzuca obowiązek alokacji i dealokacji na
    aplikację, kopiując wyniki działania do wskaźnika przekazywanego przez
    parametr. Jeśli wskaźnik jest pusty, zwracana jest tylko oczekiwana wielkość
    bufora:

    count := WinAPICall(nil);
    setlength(CharArray, count);
    WinAPICall(@CharArray[0]);

    Jest to jakieś rozwiązanie, ale komplikuje się trochę w przypadku, gdy
    przekazana ma być na przykład tablica znaków. Ba - czasami ciąg znaków może
    być efektem jakiegoś czasochłonnego procesu, a wykonywanie go dwukrotnie
    tylko po to, by za pierwszym razem zwrócić długość rezultatu jest trochę bez
    sensu. Oczywiście można trzymać ten ciąg znaków gdzieś wewnątrz plugina, ale
    dochodzą problemy z wielowątkowością (drugi wątek może zamazać dane zapisane
    przez pierwszy) i tak dalej - sprawa robi się grubsza.

    Można oczywiście rozwiązać problem trochę inaczej - na zasadzie finalizacji:

    MyPChar := PluginCall();
    // Przetwarzanie MyPChar
    PluginFinalize(MyPChar);

    Jest to też jakieś rozwiązanie; zarządzanie pamięcią ciągu znaków jest teraz
    zrzucone na plugin, ale utrudnia to trochę jego implementację.

    Może lepszym rozwiązaniem jest alokowanie pamięci w pluginie, a dealokowanie
    w aplikacji? Nie wiem, czy to jest możliwe - w sumie aplikacja i DLLka
    operują w tej samej przestrzeni adresowej, więc teoretycznie taka sztuczka
    powinna być możliwa, ale idea prezentuje się jeszcze bardziej hax0rsko niż
    dwie poprzednie...

    Czy są jakieś sprytniejsze rozwiązania?

    Pozdrawiam -- Spook.

    --
    ! ._______. Warning: Lucida Console sig! //) !
    ! || spk || www.spook.freshsite.pl / _ """*!
    ! ||_____|| spook at op.pl / ' | ""!
    ! | ___ | tlen: spoko_ws gg:1290136 /. __/"\ '!
    ! |_|[]_|_| May the SOURCE be with you! \/) \ !


  • 2. Data: 2010-02-12 00:42:31
    Temat: Re: Bezpieczne przekazywanie ciągów znaków
    Od: "Wiktor S." <wswiktor&poczta,fm@no.spam>

    > Jest to jakieś rozwiązanie, ale komplikuje się trochę w przypadku, gdy
    > przekazana ma być na przykład tablica znaków. Ba - czasami ciąg
    > znaków może być efektem jakiegoś czasochłonnego procesu, a
    > wykonywanie go dwukrotnie tylko po to, by za pierwszym razem zwrócić
    > długość rezultatu jest trochę bez sensu.

    A nie da się założyć że "ciąg nigdy nie przekroczy XXX bajtów"?

    --
    Azarien


  • 3. Data: 2010-02-12 12:34:36
    Temat: Re: Bezpieczne przekazywanie ciągów znaków
    Od: "Wojciech \"Spook\" Sura" <s...@s...op.pl>

    Użytkownik "Wiktor S." <wswiktor&poczta,fm@no.spam> napisał w wiadomości
    news:hl285s$fpm$1@news.onet.pl...
    >> Jest to jakieś rozwiązanie, ale komplikuje się trochę w przypadku, gdy
    >> przekazana ma być na przykład tablica znaków. Ba - czasami ciąg
    >> znaków może być efektem jakiegoś czasochłonnego procesu, a
    >> wykonywanie go dwukrotnie tylko po to, by za pierwszym razem zwrócić
    >> długość rezultatu jest trochę bez sensu.
    >
    > A nie da się założyć że "ciąg nigdy nie przekroczy XXX bajtów"?

    To zależy. Z jednej strony tak, bo ciągami będą przekazywane głównie
    identyfikatory lub nazwy obiektów i typów. Można więc spokojnie założyć, że
    żaden rozsądny programista nie przekroczy, powiedzmy, 256 bajtów. Z drugiej
    strony średnio uśmiecha mi się każdorazowe przepychanie przez pamięć 256
    bajtów, gdy wystarczyłoby - na przykład - 10. Drugi problem polega na tym,
    że czasem zachodzi potrzeba przekazania tablicy ciągów znaków. Będzie ona
    przekazywana jako ciąg PCharów, każdy zakończony znakiem #0. W takiej
    sytuacji nie mam już pewności, czy zmieszczę się w buforze o zadanym
    rozmiarze.

    Pozdrawiam -- Spook.

    --
    ! ._______. Warning: Lucida Console sig! //) !
    ! || spk || www.spook.freshsite.pl / _ """*!
    ! ||_____|| spook at op.pl / ' | ""!
    ! | ___ | tlen: spoko_ws gg:1290136 /. __/"\ '!
    ! |_|[]_|_| May the SOURCE be with you! \/) \ !


  • 4. Data: 2010-02-12 13:22:18
    Temat: Re: Bezpieczne przekazywanie ciągów znaków
    Od: Michoo <m...@v...pl>

    Imo najsensowniejsze byłoby "zignorowanie problemu" - skopiowanie
    kilkuset bajtów jest na tyle tanie, że zawsze można przekazywać w
    wywołaniach string i jego rozmiar. - Jeżeli aplikacja potrzebuje
    zachować stringa to go sobie kopiuje, jeżeli plugin potrzebuje stringa
    od aplikacji to podaje na niego bufor. Zaleta jest taka, że każdy
    alokuje i zwalnia swoją pamięć. A stringi nie służą przecież do
    przerzucania jakiś olbrzymich porcji danych.

    Druga możliwość to udostępnienie pluginowi metody do zaalokowania
    stringa i rozdzielenie wywołań na 2 typy:
    string jest "const" - plugin ma o niego dbać, jeżeli trzeba go zwolnić
    string nie jest "const" - w momencie przekazania stringa plugin ma
    obowiązek o nim zapomnieć. Ale to jest chyba niewygodne.


    --
    Pozdrawiam
    Michoo


  • 5. Data: 2010-02-23 18:53:07
    Temat: Re: Bezpieczne przekazywanie ciągów znaków
    Od: "\"Marsjanin\"" <z...@g...pl>

    Ja taką współpracę (program <-> DLL) zrealizowałem kiedyś następująco:

    void* Init(...); // wołane raz przy inicjalizacji (rejestracja pluginu)
    __int32 DoSomenthing(void *handle,TCHAR *Bufor,unsigned __int32
    *SizeOfBufor);
    __int32 Free(void *handle); // wołane raz przy zwalnianiu zasobów
    (wyrejestrowanie pluginu)

    Komunikacja z DoSomething wyglądała następująco:
    <CODE>
    unsigned __int32 buforSize = 0;
    __int32 error = DoSomenthing(handle,NULL,&buforSize);
    if (error >= _OK) {
    TCHAR *wynik = new TCHAR[buforSize];
    if (wynik) {
    error = DoSomenthing(handle,wynik,&buforSize);
    if (error >= _OK) {
    // obsługa wyniku
    }
    else AddError(error,TEXT("DoSomenthing(...)"));
    delete[] wynik;
    }
    }
    else AddError(error,TEXT("DoSomenthing(NULL)"));

    </CODE>

    Wewnątrz funkcji DoSomenthing "pracochłonne rzeczy" wykonywałem tylko gdy
    wywołanie było z NULL'em. Wówczas czyściłem wewnętrzne struktury (ukryte pod
    wskaźnikiem "handle") i zapamiętywałem tam bieżące wyniki.
    Wywołanie z podanym wskaźnikiem "wynik" i rozmiarem bufora kopiowało tylko
    dane ze struktur wewnętrznych do bufora użytkownika.
    Problemu z wątkami nie miałem, bo każdy wątek musiał wykonać swoje "Init" i
    "Free".

    Pozdrawiam,
    Piotr

strony : [ 1 ]


Szukaj w grupach

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: