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

新規で作成したベクターを削除する必要があります。line vector = *v は、データをもう一方にコピーするだけです。つまり、メモリ リークです。その後、delete v を呼び出します。

編集:このように使用する場合は、ポインターを使用しないでください。また、単純にベクトルを使用して、とにかくその内容を変更する関数の開始時にそれをクリアすることもできます。

本当にポインターが必要な場合は、最初にメンバー変数をポインターとして宣言し、必ず NULL で初期化し、準備を呼び出すときにポインターを削除してから、作成した新しいベクターを new で割り当てます。NULL ポインターで delete を呼び出すと、noop (操作なし) になることに注意してください。ただし、この時点では...コンストラクタで new を1回呼び出し、デストラクタで削除したい場合があります。コンテンツをクリアする準備として 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 に答える