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

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(使用前将#替换为@)

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

  • Exit() 时是否调用基本对象析构函数?

    我意识到这个问题已经出现过几次 但我试图获得上述问题的明确答案 但我不断遇到相互矛盾的信息 我需要知道的是 当我使用 exit 时 基本类对象是否被破坏 我知道需要删除动态内存 但我的意思更像是 include
  • 尝试了解使用服务打开对话框

    我已经阅读了有关使用 mvvm 模式打开对话框的讨论 我看过几个使用服务的示例 但我不明白所有部分如何组合在一起 我发布这个问题寻求指导 以了解我应该阅读哪些内容 以更好地理解我所缺少的内容 我将在下面发布我所拥有的内容 它确实有效 但从我
  • 在 CPP 类中将 C 函数声明为友元

    我需要在 C 函数中使用类的私有变量 我正在做这样的事情 class Helper private std string name public std getName return name friend extern C void in
  • MVC3中设置下拉列表中的所选项目

    我必须为视图中的下拉列表设置所选项目 但它不起作用 View div class editor label Html LabelFor model gt model Gender div div class editor field Htm
  • 从复选框列表中选择循环生成的复选框中的一个复选框

    抱歉我的英语不好 在我的 ASP NET 网站上 我从 SQL 表导入软件列表 看起来像这样 但实际上要长得多 Microsoft Application Error Reporting br br Microsoft Applicatio
  • 当事件button.click发生时,如何获取按钮名称/标签?

    我以编程方式制作按钮并将它们添加到堆栈面板中 以便每次用户导航到页面时按钮都会发生变化 我正在尝试做这样的事情 当我单击创建的按钮时 它将获取按钮的标签并转到正确的页面 但是 我无法使用 RoutedEventHandler 访问按钮元素
  • 传递 constexpr 对象

    我决定给予新的C 14的定义constexpr旋转并充分利用它 我决定编写一个小的编译时字符串解析器 然而 我正在努力保持我的对象constexpr将其传递给函数时 考虑以下代码 include
  • 有些有助于理解“产量”

    在我不断追求少吸的过程中 我试图理解 产量 的说法 但我不断遇到同样的错误 someMethod 的主体不能是迭代器块 因为 System Collections Generic List 不是迭代器接口类型 这是我被卡住的代码 forea
  • 无法注册时间触发的后台任务

    对于 Windows 8 应用程序 在 C Xaml 中 我尝试注册后台任务 很难说 但我想我的后台任务已正确注册 但是当我单击调试位置工具栏上的后台任务名称时 我的应用程序停止工作 没有任何消息 我查看了事件查看器上的日志 得到 具有入口
  • extern 声明和函数定义都在同一文件中

    我只是浏览了一下gcc源文件 在gcc c 我发现了类似的东西 extern int main int char int main int argc char argv 现在我的疑问是extern是告诉编译器特定的函数不在这个文件中 但可以
  • 如何将 .txt 文件中的数据转换为 xml? C#

    我在一个文本文件中有数千行数据 我想通过将其转换为更容易搜索的内容来轻松搜索 我希望 XML 或其他类型的大型数据结构 尽管我不确定它是否是最好的对于我的想法 每行的数据如下所示 第 31 册 托马斯 乔治 32 34 154 每本书都不是
  • 强制初始化模板类的静态数据成员

    关于模板类的静态数据成员未初始化存在一些问题 不幸的是 这些都没有能够帮助我解决我的具体问题的答案 我有一个模板类 它有一个静态数据成员 必须为特定类型显式实例化 即必须专门化 如果不是这种情况 使用不同的模板函数应该会导致链接器错误 这是
  • 获取没有显式特征的整数模板参数的有符号/无符号变体

    我希望定义一个模板类 其模板参数始终是整数类型 该类将包含两个成员 其中之一是类型T 另一个作为类型的无符号变体T 即如果T int then T Unsigned unsigned int 我的第一直觉是这样做 template
  • 在 .NET MAUI 中实现 TouchTracking

    我一直致力于将我们的应用程序从 Xamarin Forms 迁移到 NET MAUI 我们的应用程序几乎没有绘图功能 用户可以用手指进行绘图 我们用了TouchTrackingXamarin Forms 中的 nuget 包 但与 NET
  • C++ - 多维数组

    处理多维数组时 是否可以为数组分配两种不同的变量类型 例如你有数组int example i j 有可能吗i and j是两种完全不同的变量类型 例如 int 和 string 听起来您正在寻找 std vector
  • Oauth2中如何同时撤销RefreshToken和使AccessToken失效

    我正在使用 Owin Oauth2 授权和资源服务器相同 开发单页面应用程序 AngularJS Net MVC Json Rest API 的身份验证流程 我选择了 Bearer Token 路由而不是传统的 cookie session
  • WPF DataGrid / ListView 绑定到数组 mvvm

    我们假设你有 N 个整数的数组 表示行数的整数值 在模型中 该整数绑定到视图中的 ComboBox Q1 如何将数组 或数组的各个项目 绑定到 DataGrid 或 ListView 控件 以便 当您更改 ComboBox 值时 只有那么多
  • Visual Studio 2015 - Web 项目上缺少共享项目参考选项卡

    我从 MSDN 订阅升级到 Visual Studio 2015 因为我非常兴奋地阅读有关共享项目的信息 当我们想要做的只是重用代码时 不再需要在依赖项中管理 21382 个 nuget 包 所以我构建了一个测试共享项目 其中包含一些代码
  • EntityFramework 6.0.0.0 读取数据,但不插入

    我创建了一个基于服务的数据库 folderName gt Add New Item gt Data gt Service based Database文件到 WPF 应用程序中 然后我用过Database First方法并创建了Person
  • 为什么空循环使用如此多的处理器时间?

    如果我的代码中有一个空的 while 循环 例如 while true 它将把处理器的使用率提高到大约 25 但是 如果我执行以下操作 while true Sleep 1 它只会使用大约1 那么这是为什么呢 更新 感谢所有精彩的回复 但我

随机推荐

  • 导入错误:没有名为 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