C++/CLI pin_ptr 的正确用法
C++/CLI pin_ptr's usage in proper way
我是 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的成员变量,所以while 运行 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();
...
}
提前致谢。
通过固定指针解决的问题不是正常的并发问题。没有其他线程会抢占您的本机函数的执行,这可能是真的。但是,您必须考虑垃圾收集器,它可能会在 .NET 运行 时机成熟时启动。例如,系统可能 运行 内存不足,因此 运行 时间决定收集已处理的对象。这可能会在您的本机函数执行时发生,并且垃圾收集器可能会重新定位它正在使用的数组,因此您传入的指针不再有效。
黄金经验法则是在将所有数组指针和所有字符串指针传递给本机函数之前固定它们。总是。别想了,按规矩去做就好了。您的代码可能在没有固定的情况下运行很长时间,但有一天厄运会在最烦人的时候降临。
我是 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的成员变量,所以while 运行 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();
...
}
提前致谢。
通过固定指针解决的问题不是正常的并发问题。没有其他线程会抢占您的本机函数的执行,这可能是真的。但是,您必须考虑垃圾收集器,它可能会在 .NET 运行 时机成熟时启动。例如,系统可能 运行 内存不足,因此 运行 时间决定收集已处理的对象。这可能会在您的本机函数执行时发生,并且垃圾收集器可能会重新定位它正在使用的数组,因此您传入的指针不再有效。
黄金经验法则是在将所有数组指针和所有字符串指针传递给本机函数之前固定它们。总是。别想了,按规矩去做就好了。您的代码可能在没有固定的情况下运行很长时间,但有一天厄运会在最烦人的时候降临。