2013-08-26 25 views
0

我正在嘗試製作一個非常虛擬的程序,其中我在準備和搜索中插入了值。我對C++很陌生,我只是想學習一些語言的概念。當我嘗試vector = *v時,出現錯誤:試圖讀取或寫入受保護的內存。這通常表明其他內存已損壞。 我使用vC++在C++/cli實驗中使用。使用CLI傳輸指針的值時出錯使用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; 
    } 
}; 

準備方法在搜索之前使用。

的包裝,它調用的代碼在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(); 
    } 
} 
+0

我對C++有些沉悶,並沒有完全理解它應該如何完成。因此,歡迎任何建議 –

+2

在'Wrapper'構造函數中創建一個'BinarySearch'類的實例是一個好主意。 –

+0

爲什麼你使用C++/CLI?這種語言需要熟悉本地C++和.NET。我建議你在開始時使用純C++。 –

回答

1

你必須刪除你新創建的載體。線矢量= * v只是複製另一箇中的數據。換句話說,內存泄漏!所以之後請致電刪除v。

編輯:爲什麼不只是不使用指針,如果你要這樣使用它?此外,您可以簡單地使用該矢量,並在改變其內容的函數的開始處將其清除。

如果你確實需要一個指針,首先爲成員變量聲明一個指針,確保初始化爲NULL,當調用prepare時,刪除指針,然後使用new指定新創建的向量。請注意,對NULL指針調用delete會導致noop(無操作)。雖然在這一點上...你可能只是想在構造函數中調用new而在析構函數中刪除。您只需在準備清除內容時致電明確。

這是你的代碼應該是什麼樣子:

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; 
} 

OR

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指針。查看他的答案瞭解更多詳情。

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... 
}; 
+0

這就是所謂的RAiI概念嗎? –

+0

調用這個RAII會讓你進入與任何C++程序員的街頭鬥爭。在託管代碼中完成並不確定。 –