为什么用方法返回指针会使调试模式下的测试失败?

2024-01-18

当我在发布模式下启动以下测试时,它们都通过了,但在调试模式下它们都失败了。

[TestFixture]
public unsafe class WrapperTests
{
    [Test]
    public void should_correctly_set_the_size()
    {
        var wrapper = new Wrapper();
        wrapper.q->size = 1;
        Assert.AreEqual(1, wrapper.rep()->size);  // Expected 1 But was: 0
    }

    [Test]
    public void should_correctly_set_the_refcount()
    {
        var wrapper = new Wrapper();
        Assert.AreEqual(1, wrapper.rep()->refcount); // Expected 1 But was:508011008
    }
}

public unsafe class Wrapper
{
    private Rep* q;

    public Wrapper()
    {
        var rep = new Rep();
        q = &rep;
        q->refcount = 1;
    }

    public Rep* rep()
    {
        return q;
    }
}

public unsafe struct Rep
{
    public int refcount;
    public int size;
    public double* data;
}

但是如果我删除rep()方法并使得q指针公共,测试在调试和发布模式下均通过。

[TestFixture]
public unsafe class WrapperTests
{
    [Test]
    public void should_correctly_set_the_size()
    {
        var wrapper = new Wrapper();
        wrapper.q->size = 1;
        Assert.AreEqual(1, wrapper.q->size);   
    }

    [Test]
    public void should_correctly_set_the_refcount()
    {
        var wrapper = new Wrapper();
        Assert.AreEqual(1, wrapper.q->refcount);  
    }
}

public unsafe class Wrapper
{
    public Rep* q;

    public Wrapper()
    {
        var rep = new Rep();
        q = &rep;
        q->refcount = 1;
    } 
}

public unsafe struct Rep
{
    public int refcount;
    public int size;
    public double* data;
}

我不明白什么会导致这种行为?
为什么当我使用方法返回 q 的值时测试失败?


Rep是一个结构体,所以 varrep = new Rep();将存储rep堆栈上的数据(当前堆栈帧是构造函数调用)。

q = &rep;将得到一个指向rep, 所以q指向堆栈上的数据。这是这里真正的问题,因为一旦构造函数退出,它使用的堆栈空间就被认为是免费且可重用的。

你打电话时rep()在调试模式下,会创建更多堆栈帧。其中之一会覆盖您的地址处的数据q指针指向。

在释放模式下调用rep()由 JIT 内联,并且创建的堆栈帧更少。但问题仍然存在,它只是隐藏在您的示例中,因为您没有进行足够的函数调用。

例如,这个测试在发布模式下不会通过,只是因为Split call:

[Test]
public void should_correctly_set_the_refcount()
{
    var wrapper = new Wrapper();
    "abc,def".Split(',');
    Assert.AreEqual(1, wrapper.rep()->refcount);
}

作为一般规则,您不应该让指针比它们指向的数据更长寿。

要解决您的问题,您可以分配一些非托管内存,如下所示:

public unsafe class Wrapper
{
    public Rep* q;

    public Wrapper()
    {
        q = (Rep*)Marshal.AllocHGlobal(sizeof(Rep));
        q->refcount = 1;
        q->size = 0;
        q->data = null;
    }

    ~Wrapper()
    {
        Marshal.FreeHGlobal((IntPtr)q);
    }

    public Rep* rep()
    {
        return q;
    }
}

这通过了你所有的测试。

需要注意的几点:

  • 有一个释放内存的终结器
  • 内存不会被 GC 移动,就像被固定一样
  • AllocHGlobal不会将分配的内存清零,因此您应该根据需要手动清除结构字段,或者调用ZeroMemory如果结构很大,则使用 P/Invoke。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么用方法返回指针会使调试模式下的测试失败? 的相关文章

  • 创建 DirectoryEntry 实例以供测试使用

    我正在尝试创建 DirectoryEntry 的实例 以便可以使用它来测试将传递 DirectoryEntry 的一些代码 然而 尽管进行了很多尝试 我还是找不到实例化 DE 并初始化它的 PropertyCollection 的方法 我有
  • 属性对象什么时候创建?

    由于属性实际上只是附加到程序集的元数据 这是否意味着属性对象仅根据请求创建 例如当您调用 GetCustomAttributes 时 或者它们是在创建对象时创建的 或者 前两个的组合 在由于 CLR 的属性扫描而创建对象时创建 从 CLR
  • Func 方法参数的首选命名约定是什么?

    我承认这个问题是主观的 但我对社区的观点感兴趣 我有一个缓存类 它采用类型的缓存加载器函数Func
  • C++ 求二维数组每一行的最大值

    我已经设法用这个找到我的二维数组的每一行的最小值 void findLowest int A Cm int n int m int min A 0 0 for int i 0 i lt n i for int j 0 j lt m j if
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • 写入和读取文本文件 - C# Windows 通用平台应用程序 Windows 10

    有用 但在显示任何内容之前 您必须在文本框中输入内容 我想那是因为我使用了 TextChanged 事件处理程序 如果我希望它在没有用户交互的情况下显示文本文件的内容 我应该使用哪个事件处理程序 因此 我想在按下按钮时将一些数据写入 C W
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • Windows 窗体不会在调试模式下显示

    我最近升级到 VS 2012 我有一组在 VS 2010 中编码的 UI 测试 我试图在 VS 2012 中启动它们 我有一个 Windows 窗体 在开始时显示使用 AssemblyInitialize 属性运行测试 我使用此表单允许用户
  • 更改窗口的内容 (WPF)

    我创建了一个简单的 WPF 应用程序 它有两个 Windows 用户在第一个窗口中填写一些信息 然后单击 确定 这会将他们带到第二个窗口 这工作正常 但我试图将两个窗口合并到一个窗口中 这样只是内容发生了变化 我设法找到了这个更改窗口内容时
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 将日期参数传递给对 MVC 操作的 ajax 调用的安全方法

    我有一个 MVC 操作 它的参数之一是DateTime如果我通过 17 07 2012 它会抛出一个异常 指出参数为空但不能有空值 但如果我通过01 07 2012它被解析为Jan 07 2012 我将日期传递给 ajax 调用DD MM
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 如何使用 ReactiveList 以便在添加新项目时更新 UI

    我正在创建一个带有列表的 Xamarin Forms 应用程序 itemSource 是一个reactiveList 但是 向列表添加新项目不会更新 UI 这样做的正确方法是什么 列表定义 listView new ListView var
  • 如何在 C# 中播放在线资源中的 .mp3 文件?

    我的问题与此非常相似question https stackoverflow com questions 7556672 mp3 play from stream on c sharp 我有音乐网址 网址如http site com aud
  • 将变量分配给另一个变量,并将一个变量的更改反映到另一个变量中

    是否可以将一个变量分配给另一个变量 并且当您更改第二个变量时 更改会瀑布式下降到第一个变量 像这样 int a 0 int b a b 1 现在 b 和 a 都 1 我问这个问题的原因是因为我有 4 个要跟踪的对象 并且我使用名为 curr
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • 如何将字符串“07:35”(HH:MM) 转换为 TimeSpan

    我想知道是否有办法将 24 小时时间格式的字符串转换为 TimeSpan 现在我有一种 旧时尚风格 string stringTime 07 35 string values stringTime Split TimeSpan ts new

随机推荐

  • 导入错误:没有名为 matplotlib 的模块

    几个月前 Matplotlib 运行良好 但现在我不断收到错误 ImportError No module named matplotlib 我再次使用 pip 安装了 matplotlib 它不起作用 我用的是简易安装 还是行不通 pip
  • 如何连接php7和mongoDB

    我正在尝试将 PHP 7 与 mongoDB 连接 我按照以下步骤使用 pecl 安装了 新 MongoDB 驱动程序page https mongodb github io mongo php driver 指示 我可以看到 MongoD
  • 在 Rails 应用程序中执行 Ruby 脚本

    我可以在 Rails 应用程序的控制台中运行以下命令 并将 CSV 文件导入到我的数据库中 require csv row will be an array with the fields in the order they appear
  • 更新 Azure 容器实例中的 docker 映像

    我在 docker hub 的存储库中有一个镜像 我根据 docker hub 上存储库中的映像创建了 azure 容器实例 我更新了 docker hub 上存储库中的图像 如何将更改应用到容器 如果您遵循命名标签的做法 latest然后
  • 使用数据存储 (NDB)、搜索 API 或同时使用两者来查看数据?

    在 CMS 中 使用常规 NDB 查询和排序来检索客户列表 为了允许对姓名 公司名称和电子邮件进行过滤 我创建了多个 有时是多个 索引 情况并不理想 但可行 现在有 实验性的 搜索接口 https developers google com
  • 验证 NSString 中是否存在单词

    我搜索了一下 但找不到这个 可能非常简单 问题的答案 我有一个 NSString 我想检查它是否包含单词 像这样的事情 NSString sentence The quick brown fox NSString word quack if
  • 在 Woocommerce 商店页面上的类别列表中隐藏产品类别

    我想在 Woocommerce 商店页面的类别列表中隐藏某个产品类别 我找到并使用以下代码片段来执行此操作 add filter get terms exclude category 10 3 function exclude catego
  • 测试单词是否在字符串中(grepl、fuzzyjoin?)

    如果一个数据帧的两列中的字符串包含在第二个数据帧的一列的字符串中 我需要对两个数据帧进行匹配和连接 示例数据框 First lt c john jane jimmy jerry matt tom peter leah Last lt c s
  • SignTool 错误:无效选项:/fd

    我发布我的 exe 并激活自动更新 但是当我编译exe时 出现错误 严重性代码 说明 项目文件行抑制状态 错误 An 签名时发生错误 签名失败 bin Debug app publish myapp exe SignTool 错误 无效选项
  • Angular 2:ngIf 指令中比较运算符 == 和 === 之间有什么区别

    我不明白为什么这两个运算符存在 在布尔比较的情况下 和 似乎都有效 但在枚举比较的情况下只有 有效 div class interventionGroup div class interventionGroupHeader transiti
  • 查找具有特定 OMS 配置文件的 Sitecore 项目?

    我必须在 Sitecore 或者更确切地说 在内容中 中找到在 跟踪 属性中检查了特定 OMS 营销套件 配置文件的所有项目 Tracking 属性似乎存储为 XML 并具有如下原始值
  • 嵌套集合的 Lodash 映射

    我有以下收藏 var realty name Realty A entrances name Entrance A units name unitA contracts contractNo no 963 contractNo no 741
  • python,清理列表

    尝试清理 python 列表 我能够删除精确的字符串匹配 如何删除部分匹配项 exclude n Hits Sites blah blah2 partial string maybe here newlist for item in arr
  • 欧拉计划 No. 14 Haskell

    我正在尝试解决 Project Euler 的问题 14 http projecteuler net problem 14 http projecteuler net problem 14 并且我使用 Haskell 陷入了死胡同 现在 我
  • Java替换字符串中的所有方括号

    我想从字符串中删除方括号 但我不知道如何操作 String str Chrissman 1 str replaceAll String temp str split System out println Nickname temp 0 Po
  • 计算 JMS 队列中的消息数

    检查 JMS 队列并获取其中所有消息的最佳方法是什么 如何统计队列中消息的数量 Thanks 使用 JmsTemplate public int getMessageCount String messageSelector return j
  • HasColumnType 和 Database generated 的正确用法是什么

    我正在将大约 80 个实体的大量 EF 模型从 EF4 迁移到 EF6 并且还将其从 Designer EDMX 生成数据库更改为 Code First 数据库 现在 我正在使用 EF Fluent api 配置实体关系 但我不确定是否正确
  • 更新后pgadmin无法登录

    刚刚将 pgadmin4 更新到版本 4 8 现在它不接受 ssh 隧道密码进入服务器 我收到以下错误消息 Failed to decrypt the SSH tunnel password Error utf 8 codec can t
  • 了解 QEMU 的好来源是什么?

    您会推荐什么书或网站来了解 QEMU 我想查看一些使用示例以及如何使用 API 最佳资源 主要 QEMU 使用文档 http wiki qemu org Manual Qemu 手册页 http manpages ubuntu com ma
  • 为什么用方法返回指针会使调试模式下的测试失败?

    当我在发布模式下启动以下测试时 它们都通过了 但在调试模式下它们都失败了 TestFixture public unsafe class WrapperTests Test public void should correctly set