Освобождение памяти - PullRequest
       0

Освобождение памяти

1 голос
/ 07 апреля 2020

У меня есть C ++ библиотека , которую я изменяю и компилирую как .dll для использования в C# приложении. Библиотека состоит из одной библиотеки заголовков, которая теперь выглядит следующим образом:

#include <array>
#include <vector>
#include <cmath>

typedef std::array<double, 2> Point;
std::vector<Point> samples;

extern "C" {
    __declspec(dllexport) void __cdecl initSamplers();
    __declspec(dllexport) unsigned int __cdecl ldbnBNOT(const unsigned int nbPts);
    __declspec(dllexport) Point* __cdecl getPointAt(unsigned int i);
    __declspec(dllexport) void __cdecl releasePointAt(double* pArray);
}

unsigned mirror[256];

inline double phi(const unsigned &i){
    const unsigned ONE = 0x1000000;                                            
    const double scl = 1.0 / ONE;
    return scl * (
            mirror[(i >> 16) & 255] +
            (mirror[(i >> 8) & 255] << 8) +
            (mirror[i & 255] << 16)
            );
}

extern void __cdecl initSamplers(){
    for (unsigned i = 0; i < 256; i++) {
        mirror[i] = (i >> 7) + ((i >> 5) & 2) + ((i >> 3) & 4) + ((i >> 1) & 8) + ((i << 1) & 16) + ((i << 3) & 32) + ((i << 5) & 64) + ((i << 7) & 128);
    }
}

extern Point* __cdecl getPointAt(unsigned int i){
    if (samples.size() > 0) return &samples.at(i);
    else return nullptr;
}

extern void __cdecl releasePointAt(double* pArray){
    delete[] pArray;
}

extern unsigned int __cdecl ldbnBNOT(const unsigned int nbPts){
    samples.clear();
    auto n = std::floor(std::sqrt((double)nbPts));
    Point p;

    double inv = 1.0 / n;
    unsigned mask = 128 - 1;                                                
    unsigned shift = std::log2(128);
    for (unsigned Y = 0; Y < n; Y++) {
        for (unsigned X = 0; X < n; X++) {
            unsigned index = ((Y & mask) << shift) + (X & mask);
            double u = phi((Y & 0xfffffff0) + (lutLDBN_BNOT[index] & 0xf));
            double v = phi((X & 0xfffffff0) + (lutLDBN_BNOT[index] >> 4));
            p[0] = inv * (X + u);
            p[1] = inv * (Y + v);
            samples.push_back(p);
        }
    }
    return samples.size();
}

Затем внутри моего приложения C# я импортирую свою DLL и затем вызываю различные функции. Я выгляжу примерно так:

namespace RandomPointGenerator
{
    internal static class UnsafeNativeMethods
    {
        const string _dllLocation = "LowDiscBlueNoise.dll";
        [DllImport(_dllLocation)]
        public static extern void initSamplers();

        [DllImport(_dllLocation)]
        public static extern int ldbnBNOT(int samples);

        [DllImport(_dllLocation)]
        public static extern IntPtr getPointAt(int i);

        [DllImport(_dllLocation)]
        public static extern void releasePointAt(IntPtr ptr);
    }

    public class Populate2D 
    {
        public Populate2D()
        : base("Name", "Nickname", "Description")
        {
        }

        public static void InitSamplers(){
            UnsafeNativeMethods.initSamplers();
        }

        public static int GeneratePts(int samples){
            return UnsafeNativeMethods.ldbnBNOT(samples);
        }

        public static Point3d getPointAt(int i){
            IntPtr ptr = UnsafeNativeMethods.getPointAt(i);
            double[] pt = new double[2];
            Marshal.Copy(ptr, pt, 0, 2);
            if (pt.Length < 0) pt = new double[2] { 0.0, 0.0 };
            //releasePointAt(ptr);
            return new Point3d(pt[0], pt[1], 0.0);
        }

        public static void releasePointAt(IntPtr ptr){
            UnsafeNativeMethods.releasePointAt(ptr);
        }

        protected override void Compute(){
            int samples = 200;

            List<Point3d> points = new List<Point3d>();
            InitSamplers();
            int pointCount = GeneratePts(samples);
            double[] p;
            for(int i = 0; i < pointCount - 1; i++)
            {
                points.Add(getPointAt(i));
            }
        }
    }
}

Итак, внутри моего Compute метода я создаю точки в библиотеке C ++, а затем использую метод getPointsAt для перенести 2D-массив в мою программу. Мой вопрос заключается в том, нужно ли мне затем отпустить указатель обратно в моей библиотеке C ++. Вы можете видеть, что я добавил releasePointAt метод, который должен освободить память, но когда я запускаю его, это приводит к тому, что мое приложение обрабатывает sh. Это работает, если я закомментирую эту строку (поэтому она никогда не освобождает ее), но я не уверен, вызывает ли это утечку памяти или нет. Кто-нибудь может дать какие-либо указания относительно того, нужно ли мне на самом деле отпустить указатель или нет?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...