【问题标题】:Do by ref parameters guarantee that the variable stays at its current position in memory?by ref 参数是否保证变量保持在内存中的当前位置?
【发布时间】:2016-04-19 23:14:22
【问题描述】:

I know what passing by ref is and what it means,但是 ref 传递的对象到底发生了什么?是否保证在使用引用时对象保持在内存中的当前位置?

变量是否是局部变量有区别吗?

我最感兴趣的是内存中发生的事情。

一些背景信息: 我编写了一个简单的测试程序,它存储 ref 传递的对象的内存地址,并注意到 C# 喜欢在内存中移动对象。但我认为奇怪的是,所使用的对象是函数的局部变量。这自动让我认为对象的引用不能在内存中移动,因为它在堆栈上。但显然我错过了一些东西。使用 ref 时我收到了什么样的内存?

【问题讨论】:

标签: c#


【解决方案1】:

我们来看一个例子:

static void callee(ref int y) { ... }

static void caller() 
{
    int x = 3;
    callee(x);
}

它到底对 ref 传递的对象做了什么?

对象没有任何反应。通过 ref 传递参数会创建一个别名,这意味着xy 引用了相同的 存储位置。

是否保证对象在使用引用时保持在内存中的当前位置?

不,不能保证对象将保留在内存中的同一位置。 CLR 的特定实现可能会决定移动某些对象,但它会自行决定是否这样做。你对此没有任何保证。您只能保证xy 始终引用相同的存储位置。

如果需要修复内存中的存储位置,请使用 C# fixed Statement

我最感兴趣的是内存中发生的事情。

这是您正在使用的特定 C# 运行时的实现细节。合约很简单:如果你使用fixed,保证内存中的位置是固定的。如果你不这样做,那就不是。

【讨论】:

  • 如果无法保证,那么它应该如何处理 DLL 文件中的非托管代码?还是实际上它不起作用的情况,即使是简单的值类型,除非你使用 fixed 关键字?我正在使用 Microsoft Visual C# 2010。
  • @JerryHundric:在非托管 DLL 的情况下,互操作编组器会自动完成所有繁重的工作:It can copy or pin data as required. 您无需担心。
  • 是的,我希望有更多关于它如何与非托管代码一起工作的内容,因为这就是我观察到的方式。如果我通过 ref 传递给非托管代码,然后通过 ref 传递给回调函数,一切都很好。但是,如果我调用一个首先存储 ref 值的非托管函数,然后在该函数返回后,调用另一个非托管函数将 ref 传递给回调,我发现它不起作用。我可能应该更清楚地说明这个问题是针对非托管代码的。
  • @JerryHundric:也许一个关于minimal reproducible example特定 案例的新问题可能是个好主意。与您当前的广泛问题相比,它可能会得到社区更好的反应,甚至可能会在这里吸引非托管/互操作专家(请务必适当地标记您的新问题,以便他们看到)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-08
  • 2018-12-06
  • 2017-08-09
  • 2011-10-04
  • 1970-01-01
  • 1970-01-01
  • 2022-12-11
相关资源
最近更新 更多