2

我是 C++/CLI 的新手。
我已经知道 pin_ptr 的功能是让 GC 不学习指定对象。

现在让我给你看msdn的例子。
https://msdn.microsoft.com/en-us//library/1dz8byfh.aspx

// pin_ptr_1.cpp  
// compile with: /clr   
using namespace System;  
#define SIZE 10  

#pragma unmanaged  
// native function that initializes an array  
void native_function(int* p) {  
   for(int i = 0 ; i < 10 ; i++)  
    p[i] = i;  
}  
#pragma managed  

public ref class A {  
private:  
   array<int>^ arr;   // CLR integer array  

public:  
   A() {  
      arr = gcnew array<int>(SIZE);  
   }  

   void load() {  
     pin_ptr<int> p = &arr[0];   // pin pointer to first element in arr  
     int* np = p;   // pointer to the first element in arr  
     native_function(np);   // pass pointer to native function  
   }  

   int sum() {  
      int total = 0;  
      for (int i = 0 ; i < SIZE ; i++)  
         total += arr[i];  
      return total;  
   }  
};  

int main() {  
   A^ a = gcnew A;  
   a->load();   // initialize managed array using the native function  
   Console::WriteLine(a->sum());  
}  

听到的是问题。

没关系,传递的对象(arr)没有固定?因为非托管代码(native_function)是同步操作并在 C++/CLI 代码(加载)之前完成

即使主要逻辑正在运行,gc destory arr 是否还有机会?(我认为 A 是 main 的堆栈变量,而 arr 是 A 的成员变量,所以在运行 main 时,它应该是可见的)

如果是这样,我们如何保证 A 在调用负载之前就在那里?
(仅当不在本机代码中运行时?)

int main() {
  A^ a = gcnew A; 
  // I Think A or arr can be destroyed in here, if it is able to be destroyed in native_function. 
  a->load();  
  ...
}

提前致谢。

4

1 回答 1

1

通过固定指针解决的问题不是正常的并发问题。可能没有其他线程会抢占您的本机函数的执行。但是,您必须将垃圾收集器计算在内,只要 .NET 运行时认为合适,它就会启动。例如,系统可能内存不足,因此运行时决定收集已处置的对象。这可能会在您的本机函数执行时发生,并且垃圾收集器可能会重新定位它正在使用的数组,因此您传入的指针不再有效。

黄金法则是在将所有数组指针和所有字符串指针传递给本机函数之前固定它们。总是。别想了,按规矩办就好。您的代码可能会在很长一段时间内正常工作而无需固定,但有一天,不幸会在最烦人的时候打击您。

于 2017-08-05T15:12:18.473 回答