do tnet mallo c: двойное освобождение объекта при вызове функции DllImport - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть C# программа, вызывающая внешнюю функцию. C Функция имеет следующий вид:

char *confd_ns2prefix(u_int32_t ns)
{
    struct schema *schema = find_schema(ns);

    if (schema != NULL)
        return (char *)schema->prefix;
    return NULL;
}

Я объявил функцию следующим образом:

[DllImport("libconfd.so", SetLastError = true)]
public static extern string confd_ns2prefix(UInt32 ns);

При двойном вызове функции, например:

Console.WriteLine(libconfd.confd_ns2prefix((uint)1826703833));
Console.WriteLine(libconfd.confd_ns2prefix((uint)1826703833));

Во второй раз я получу ошибку двойного освобождения:

ncm
do tnet (39827,0x11dd24dc0) mallo c: двойное освобождение от объекта 0x7f8182037b20
do tnet (39827,0x11dd24dc0) mallo c: *** установить точку останова в malloc_error_break для отладки

Похоже, маршаллер пытается освободить объект дважды, но я понятия не имею, почему ... На самом деле, оно даже не должно освобождать его.

Есть идеи?

1 Ответ

0 голосов
/ 09 апреля 2020

На самом деле все было объяснено здесь: https://docs.microsoft.com/en-us/dotnet/framework/interop/default-marshaling-behavior

Однако, если вы определяете метод как прототип вызова платформы, замените каждый тип BSTR на тип String, и вызовите MethodOne, общеязыковая среда выполнения пытается освободить b дважды. Вы можете изменить поведение маршалинга, используя типы IntPtr, а не типы String.

Среда выполнения всегда использует метод CoTaskMemFree для освобождения памяти. Если память, с которой вы работаете, не была выделена с помощью метода CoTaskMemAllo c, вы должны использовать IntPtr и вручную освободить память, используя соответствующий метод.

Я исправил это следующим образом

[DllImport("libconfd.so", SetLastError = true)]
public static extern IntPtr confd_ns2prefix(UInt32 ns);

public static  string confd_ns2prefix_w(UInt32 ns) {
    return Marshal.PtrToStringAnsi(confd_ns2prefix(ns));
}
...