Конференция "Начинающим" » SNMP и Delphi 2009 - непонятки с указателем [WinXP]
 
  • tytus (13.08.09 12:07) [0]
    Добрый день мастера.
    Есть файл Snmp_Api, в нем записи:

     PAsnOctetString = ^TAsnOctetString;
     TAsnOctetString = record
       stream: PByte;
       length: UINT;
       dynam: BOOL;
     end;

     PAsnAny = ^TAsnAny;
     TAsnAny = record
       asnType: BYTE;
       case Integer of      0: (number: TAsnInteger32);          { ASN_INTEGER, ASN_INTEGER32 }
         1: (unsigned32: TAsnUnsigned32);     { ASN_UNSIGNED32 }
         2: (counter64: TAsnCounter64);       { ASN_COUNTER64 }
         3: (str: TAsnOctetString);           { ASN_OCTETSTRING }
         4: (bits: TAsnBits);                 { ASN_BITS }
         5: (obj: TAsnObjectIdentifier);      { ASN_OBJECTIDENTIFIER }
         6: (sequence: TAsnSequence);         { ASN_SEQUENCE }
         7: (address: TAsnIpAddress);         { ASN_IPADDRESS }
         8: (counter: TAsnCounter32);         { ASN_COUNTER32 }
         9: (gauge: TAsnGauge32);             { ASN_GAUGE32 }
        10: (ticks: TAsnTimeticks);           { ASN_TIMETICKS }
        11: (arbitrary: TAsnOpaque);          { ASN_OPAQUE }
     end;

     TAsnObjectName = TAsnObjectIdentifier;
     TAsnObjectSyntax = TAsnAny;

     PSnmpVarBind = ^TSnmpVarBind;
     TSnmpVarBind = record
       name: TAsnObjectName;
       value: TAsnObjectSyntax;
     end;

     PSnmpVarBindList = ^TSnmpVarBindList;
     TSnmpVarBindList = record
       list: PSnmpVarBind;
       len: UINT;
     end;



    В главном юните есть процедура, для получения результатов SNMP запросов
    procedure TMainFm.PrintVarBind(const VarBind: TSnmpVarBind);


    объявлена переменная
    var
     P: PByte;



    затем, втеле процедуры, определяем тип ответа:

    with VarBind.value do
       case asnType of
    ...
         ASN_OCTETSTRING:
           begin
             A[2] := 'Octet String';
             if str.length > 0 then
             begin
               IsAscii := True;
               P := str.stream;
               for i := 0 to str.length - 1 do
               begin
                 if not (P^ in [0, 32..127]) then    // <-- ТУТ ОШИБКА!!!
                 begin
                   IsAscii := False;
                   Break;
                 end;
                 Inc(P);
               end;
    ...
     end;



    В Delphi 2007 этот код работает нормально, длина строки 89 (к примеру). В D2009 длина строки = 1, адрес str.stream равен $59 - вот и ошибка - "read from address $00000059"..

    Подскажите, как с этим бороться.
  • DVM © (13.08.09 12:21) [1]
    что такое str ?
  • tytus (13.08.09 12:34) [2]
    >DVM  (13.08.09 12:21) [1]
    PAsnAny = ^TAsnAny;
    TAsnAny = record
      asnType: BYTE;
      case Integer of      0: (number: TAsnInteger32);          { ASN_INTEGER, ASN_INTEGER32 }
        1: (unsigned32: TAsnUnsigned32);     { ASN_UNSIGNED32 }
        2: (counter64: TAsnCounter64);       { ASN_COUNTER64 }
        3: (str: TAsnOctetString);           { ASN_OCTETSTRING } <-- Вот ОНО - str!!!
        4: (bits: TAsnBits);                 { ASN_BITS }
        5: (obj: TAsnObjectIdentifier);      { ASN_OBJECTIDENTIFIER }
        6: (sequence: TAsnSequence);         { ASN_SEQUENCE }
        7: (address: TAsnIpAddress);         { ASN_IPADDRESS }
        8: (counter: TAsnCounter32);         { ASN_COUNTER32 }
        9: (gauge: TAsnGauge32);             { ASN_GAUGE32 }
       10: (ticks: TAsnTimeticks);           { ASN_TIMETICKS }
       11: (arbitrary: TAsnOpaque);          { ASN_OPAQUE }
    end;

  • DVM © (13.08.09 15:07) [3]

    > tytus

    вероятно у тебя какое то несоответствие между значением str.length и реальной длиной str.stream. Случайно из строки типа string ничего туда не переносилось?
  • tytus (13.08.09 15:33) [4]
    > DVM ©   (13.08.09 15:07) [3]
    да нет, ничего...
    вот как отправляю запрос:
    1)
    SnmpMgrStrToOid(PAnsiChar(sOID), @OID);

    где OID - TAsnObjectIdentifier, sOID - текст эдита.
    2)
    with VarBindList do
       begin
         list :=  SnmpUtilMemAlloc(SizeOf(TSnmpVarBind));
         len := 1;
         list^.name := OID;
         list^.value.asnType := ASN_NULL;
       end;


    3)
    RequestType := SNMP_PDU_GET;
       RetVal := SnmpMgrRequest(Session, RequestType, @VarBindList,
           @ErrorStatus, @ErrorIndex);


    4) - получаем ответ
       
    PrintVarBind(VarBindList.list^);



    Несоответствие может произойти, если компиляторы D2007 и D2009 по-разному работают.
    В Д2007-ом работает, а в Д2009  - ошибка...

    function SnmpMgrRequest(session: PSnmpMgrSession; requestType: Byte; variableBindings: PSnmpVarBindList;
     errorStatus: PAsnInteger32; errorIndex: PAsnInteger32): SNMPAPI; stdcall;

    function SnmpMgrRequest; external  'mgmtapi.dll'  name  'SnmpMgrRequest';

  • Сергей М. © (13.08.09 17:18) [5]

    > sOID - текст эдита


    Что значит "текст эдита" ?
    Некая переменная типа string, в которую ты ранее сохранил значение св-ва Edit.Text ? Или что ?
  • Сергей М. © (13.08.09 17:21) [6]
    И какого лешего у тебя отсутствует анализ результата. возвращаемого функцией SnmpMgrStrToOid() ? Хотя бы в целях отладки ?
  • tytus (13.08.09 17:47) [7]
    > Сергей М. ©   (13.08.09 17:18) [5]
    именно так.
    > Сергей М. ©   (13.08.09 17:21) [6]
    анализ есть, не писал для краткости...
     try
    ...
       if not SnmpMgrStrToOid(PAnsiChar(sOID), @OID) then
       begin
         Raise Exception.CreateFmt('Invalid Oids, ''%s'', specified.', [sOID]);
       end;
    ...
     finally
       SnmpMgrClose(Session);
     end;

  • Сергей М. © (13.08.09 20:47) [8]

    > tytus   (13.08.09 17:47) [7]
    > именно так


    Ну а раз именно так, то первым параметром ты передал указатель на строку в юникоде, хотя ф-ция ожидает ansi-строку
  • tytus (14.08.09 10:08) [9]
    > Сергей М. ©   (13.08.09 20:47) [8]

    > первым параметром ты передал указатель на строку в юникоде

    var
     sOID: AnsiString;
    begin
     sOID := '.1.3.6.1.2.1.1.1.0'; <-- это разве не ANSI ???
     SnmpMgrStrToOid(PAnsiChar(sOID), @OID);



    к тому же, в процедуре PrintVarBind есть функция
    SnmpUtilOidToA(@VarBind.name),

    которая возвращает заданный OID,
    следовательно, строка передается правильно.
  • Сергей М. © (14.08.09 10:16) [10]
    Я же спросил:

    > Некая переменная типа string .. ?


    Ты отвечаешь:

    > именно так


    А теперь говоришь, что не именно и не так:

    > var
    >  sOID: AnsiString;
  • tytus (14.08.09 10:44) [11]
    > Сергей М. ©   (14.08.09 10:16) [10]
    Вполне можно было предположить, что я правильно оперировал типами строк... и никоим образом не хотел вас обмануть.
    Намутили embarcadero со своим юникодом IDE и всего прочего...
    но все равно, хочеться разобраться, в чем тут дело...
    Какие еще есть варианты?
  • Дмитрий Белькевич (14.08.09 14:12) [12]

    > Намутили embarcadero со своим юникодом IDE и всего прочего.
    > .. но все равно, хочеться разобраться, в чем тут дело...
    > Какие еще есть варианты?


    Намутили, если уж на то пошло, еще Майкрософт. А Эмбаркадеро проделало огромадную работу, что бы к этому всему 'счастью' приспособиться. Имейте уважение.
  • tytus (14.08.09 16:14) [13]
    > Дмитрий Белькевич   (14.08.09 14:12) [12]
    так почему-же в Д2009 не работает сей код?
    Неверно определяется указатель на данные в
    VarBindList

    .
  • tytus (17.08.09 16:51) [14]
    Вот нашел решение:
    {$Align 4}

 
Конференция "Начинающим" » SNMP и Delphi 2009 - непонятки с указателем [WinXP]
Есть новые Нет новых   [134439   +39][b:0][p:0.004]