0

我正在尝试制作一个非常虚拟的程序,在其中插入值准备并在搜索中搜索。我对 C++ 很陌生,我只是想学习一些语言的概念。当我尝试 时vector = *v,我收到一个错误:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。 我正在使用 vc++ 在 c++/cli 实验中使用。

我究竟做错了什么?

#include "stdafx.h"
#include <algorithm>
#include <vector>
#include <ostream>
#include <iostream>

#pragma once

class BinarySearch
{
public:

    BinarySearch(void)
    {
    }

    virtual ~BinarySearch(void)
    {
    }

    int search(int key)
    {
         std::vector<int>::iterator low,up;
         low=std::lower_bound (vector.begin(), vector.end(), key); 

         return low - vector.begin();
    }

    std::vector<int> vector;

    void prepare(void)
    {
        std::vector<int>* v = 
            new std::vector<int>();

        int max = std::pow(33, 3);

        for(int i=0; i < max; i++) {
            v->push_back(i);
        }

        vector = *v;
    }
};

在搜索之前使用 prepare 方法。

包装器,它调用 C++ 中的代码:

namespace Native {
    public ref class Wrapper
    {
    public:

        Wrapper(void)
        {
        }

        BinarySearch* b;

        void Prepare(void)
        {
            b->prepare();       
        }

        int Search(int i)
        {
            return b->search(i);
        }
    };
}

c#中的调用者:

class Program
{
    static void Main(string[] args)
    {
        var w = new Wrapper();
        w.Prepare();
        var position = w.Search(12);
        Console.WriteLine("Array.BinarySearch p: {0}", position);
        Console.ReadLine();
    }
}
4

2 回答 2

2

您只是忘记分配b指针。因此,当您在 Prepare() 包装方法中取消引用它时,您的代码当然会崩溃。只需在构造函数中创建 BinarySearch 类的实例。

您还需要确保本机对象再次被销毁。实现析构函数和终结器,这样就可以保证完成,即使 C# 代码没有释放对象。像这样:

public ref class Wrapper 
{
private:
    BinarySearch* b;
public:
    Wrapper(void) : b(new BinarySearch) {}
    ~Wrapper() { delete b; b = nullptr; }
    !Wrapper() { this->~Wrapper(); }

    void Prepare(void) {
        if (b == nullptr) throw gcnew ObjectDisposedException("Wrapper");
        b->prepare();       
    }
    // etc...
};
于 2013-08-26T16:12:51.243 回答
1

您必须删除使用新创建的矢量。线向量 = *v 只是复制另一个中的数据。换句话说,内存泄漏!所以之后调用 delete v 。

编辑:如果你打算这样使用它,为什么不直接使用指针呢?此外,您可以简单地使用向量并在更改其内容的函数开始时将其清除。

如果你真的需要一个指针,首先将成员变量声明为指针,确保初始化为 NULL,然后在调用 prepare 时删除指针,然后将你创建的新向量分配给新向量。请注意,对 NULL 指针调用 delete 会导致 noop(无操作)。虽然此时......您可能只想在构造函数中调用一次 new 并在析构函数中删除。您只需要在准备清除内容时调用 clear。

这就是你的代码应该是这样的:

std::vector<int> vector;

void prepare(void)
{
    std::vector<int>* v = 
    new std::vector<int>();

    int max = std::pow(33, 3);

    for(int i=0; i < max; i++) {
        v->push_back(i);

    vector = *v;
    delete v;
}

或者

std::vector<int> vector;

void prepare(void)
{
    vector.clear();

    int max = std::pow(33, 3);

    for(int i=0; i < max; i++) {
        vector.push_back(i);
    }
}

编辑:正如汉斯所说,您没有为包装器中的 b 指针分配任何内容。查看他的答案以获取更多详细信息。

于 2013-08-26T14:36:00.737 回答