PInvoke - чтение значения строкового поля - & # 8220; Попытка чтения или записи в защищенную память & # 8221;

StackOverflow https://stackoverflow.com/questions/1607380

  •  05-07-2019
  •  | 
  •  

Вопрос

У меня проблемы с доступом к некоторым строковым полям в интерфейсе COM. Вызов целочисленных полей не приводит к ошибке. При попытке вызова clientID () , deviceID () или key () я получаю старую " попытку чтения или записи защищенная память " ошибка.

Вот код исходного кода: (код получен из здесь )

[scriptable, uuid(fab51c92-95c3-4468-b317-7de4d7588254)]
interface nsICacheEntryInfo : nsISupports
{
    readonly attribute string  clientID;
    readonly attribute string deviceID;
    readonly attribute ACString key;
    readonly attribute long  fetchCount;
    readonly attribute PRUint32  lastFetched;
    readonly attribute PRUint32  lastModified;
    readonly attribute PRUint32  expirationTime;
    readonly attribute unsigned long  dataSize;
    boolean  isStreamBased();
};

Вот код C # для доступа к интерфейсу:

[Guid("fab51c92-95c3-4468-b317-7de4d7588254"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface nsICacheEntryInfo
{
    string clientID();
    string deviceID();
    nsACString key();
    int fetchCount();
    Int64 lastFetched();
    Int64 lastModified();
    Int64 expirationTime();
    uint dataSize();
    [return: MarshalAs(UnmanagedType.Bool)]
    bool isStreamBased();
}

Есть ли какие-либо предложения относительно того, почему простое чтение поля должно вызвать у меня нарушения прав доступа?

Это было полезно?

Решение

Строки в этом интерфейсе являются вариантами строк в стиле C (char *), но COM Interop по умолчанию обрабатывает строки как BSTR. У вас есть маршаллер, который пытается прочитать неправильный тип строки, а затем освободить ее с помощью распределителя памяти CoTask, поэтому неудивительно, что вы получили нарушение доступа. Если ваши строки имеют параметры [In], вы можете просто украсить их соответствующим атрибутом MarshalAs, но это не будет работать с параметрами возвращаемого значения. Поэтому вам нужно маршалировать их как IntPtrs, а затем вручную маршалировать и освобождать основную память.

Я бы попробовал следующее:

[Guid("fab51c92-95c3-4468-b317-7de4d7588254"), ComImport, 
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface nsICacheEntryInfo
{
    IntPtr clientID { get; }
    IntPtr deviceID { get; }
    IntPtr key { get; }
    int fetchCount { get; }
    uint lastFetched { get; }
    uint lastModified { get; }
    uint expirationTime { get; }
    uint dataSize { get; }
    [return: MarshalAs(UnmanagedType.Bool)]
    bool isStreamBased();
}

Как упоминал Крис выше, PRUint32 на самом деле являются 32-битными, а не 64-битными целыми числами без знака, поэтому я их изменил. Кроме того, я изменил методы на свойства, так как это лучше отражает значение idl, поскольку все они доступны только для чтения, что на самом деле не влияет на макет.

Строки для clientID и deviceID могут быть прочитаны с использованием Marshal.PtrToStrAnsi следующим образом:

        nsIMemory memoryManagerInstance = /*maybe get this from somewhere*/;
        nsICacheEntryInfo cacheEntryInstance = /*definitely get this from somewhere*/;
        IntPtr pClientID = cacheEntryInstance.clientID;
        string clientID = Marshal.PtrToStringAnsi(pClientID);

        NS_Free(pClientID);

        //or

        memoryManagerInstance.free(pClientID);

Используете ли вы NS_Free или интерфейс памяти для освобождения строк, зависит от того, как вы используете всю установку xpcom. Значение ключа является абстрактной строкой, поэтому ее представление зависит от того, откуда оно взято. Похоже, однако, что его обычно можно рассматривать как указатель на строку ANSI, как и другие.

У меня нет настроек, чтобы попробовать что-то подобное для вас, и документация, по меньшей мере, несколько непрозрачна, поэтому вам, возможно, придется немного подправить это.

Другие советы

Что, если вы примените параметр state [return: MarshalAs (UnmanagedType.BStr)] к clientID и deviceID?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top