c - 我是否需要在 C++/CLI 中删除非托管对象

标签 c memory-management c++-cli

我有一个调用 C 结构和方法的 C++/CLI 方法:

在 C 头文件中:

typedef struct {
  int left;
  int top;
  int right;
  int bottom;
} frame_t;

typedef struct {
  int     width;
  int     height;
  int     group;
  int     nb_hints;
  frame_t *hints;

  frame_t view;
  frame_t dest;
  int     page;
} image_t;

int resize_to_fill(image_t *image, int width, int height);

C++/CLI 包装器:

public ref class Frame {
public:
    int Left;
    int Top;
    int Right;
    int Bottom;

    property int Width {
        int get() {
            return (Right - Left);
        }
    }
    property int Height {
        int get() {
            return (Bottom - Top);
        }
    }

    Frame() {
        Top = 0;
        Left = 0;
        Bottom = 0;
        Right = 0;
    }

internal:
    frame_t ToNative() {
        frame_t f;
        f.left = Left;
        f.top = Top;
        f.right = Right;
        f.bottom = Bottom;
        return f;
    }

    Frame(const frame_t &f) {
        Left = f.left;
        Top = f.top;
        Right = f.right;
        Bottom = f.bottom;
    }
};

public ref class Image {
private:
    void init(int nb_hints) {
        this->view = gcnew Frame();
        this->dest = gcnew Frame();
        this->page = 0;
        this->Hints = gcnew array<Frame^>(nb_hints);
    }

public:
    int Width;
    int Height;
    array<Frame^>^ Hints;

    property int Group {
        int get() {
            return group;
        }
    }
    property int Page {
        int get() {
            return this->page;
        }
    }
    property Frame^ View {
        Frame^ get() {
            return this->view;
        }
    }
    property Frame^ Dest {
        Frame^ get() {
            return this->dest;
        }
    }

    Image(int nb_hints) {
        this->init(nb_hints);
    }

    Image() {
        this->init(0);
    }

internal:
    Frame^ view;
    Frame^ dest;
    int page;
    int group;

    Image(image_t native) {
        this->Width = native.width;
        this->Height = native.height;

        this->Hints = gcnew array<Frame^>(native.nb_hints);
        for (int i = 0; i < native.nb_hints; i++)
        {
            this->Hints[i] = gcnew Frame(native.hints[i]);
        }

        this->group = native.group;
        this->page = native.page;
        this->dest = gcnew Frame(native.dest);
        this->view = gcnew Frame(native.view);
    }

    image_t ToNative() {
        image_t i;
        i.width = this->Width;
        i.height = this->Height;
        i.group = this->Group;

        // hints
        i.nb_hints = this->Hints->Length;
        i.hints = new frame_t[this->Hints->Length];
        for (int nb = 0; nb < this->Hints->Length; nb++)
        {
            i.hints[nb] = this->Hints[nb]->ToNative();
        }

        // output values
        i.page = this->Page;
        i.view = this->View->ToNative();
        i.dest = this->Dest->ToNative();

        return i;
    }
};

// later, in another class
static int ResizeToFill(Image^ %image, int width, int height) {
    image_t native = image->ToNative();

    int result = resize_to_fill(&native, width, height);

    image = gcnew Image(native);

    // do I need to do this ?
    delete *native;

    return result;
}

我需要删除原生结构实例吗?

我已经搜索过这个答案,但它更多地涉及处理托管资源而不是非托管资源,这对大多数人来说似乎是显而易见的。我是 C/C++ 的新手,所以我没有所有的内存管理 react 。

最佳答案

image = gcnew Image(native);

这完全取决于这条语句的作用。您使用的库不是普通库,并且 Image 包装器类不是 System::Drawing::Image,因此无法仅从您的代码片段中分辨出来。

这个库的程序员可以通过两种方式实现它。如果他采取了聪明的方式,那么他就把它作为你的问题并创建了一个浅拷贝。换句话说,一个新的 Image 实例与native 共享相同的底层像素缓冲区。或者他可以创建一个深拷贝 并为 Image 对象创建一个新的像素缓冲区。在这种情况下,您可以安全地销毁 image_t 对象。

.NET 中也存在这种差异,Bitmap::Clone() 进行浅拷贝,Bitmap(Image^) 构造函数进行深拷贝。两者之间存在巨大差异,浅拷贝最多需要几把纳秒。如果图像很大,深层复制需要的时间会长得多,可能是毫秒

如果处理浅拷贝非常痛苦,您可能无法更改 Image 类的终结器。您必须保留 image_t* 并获得一个良好的信号,表明 Image 对象不再使用,以便您可以安全地删除它。您将不得不显着重构您的代码。如果你猜错了,那么你就会遇到一个非常讨厌的问题,它不能保证让你的代码崩溃。您有一个不太可能导致访问冲突的悬空指针。当您测试时似乎工作正常,损坏显示的图像或在您不注意时无法诊断地崩溃您的程序。

查看库的源代码或文档以了解它的作用非常重要。

关于c - 我是否需要在 C++/CLI 中删除非托管对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29387812/

相关文章:

iOS开发: How am I mismanaging memory in this code?

java - 在 Java 中分配大量数组时避免内存碎片

c++-cli - 将 BoostTest 与 C++/CLI 一起使用 : possible or not?

c# - 将字符串从 C++/CLI 类库传递到 C#

c++-cli - C++-CLI 复制构造函数的正确形式是什么?

条件跳转或移动取决于未初始化的值和在 retval 上分配的指针

c - 在大于 65KB 的字符串上使用 printf 遇到了哪个瓶颈?

C系统函数返回sh : Invoke-Item command not found

c - 为什么 C 函数会自动改变数组?

c - Linux:伙伴系统空闲内存