内存管理-如何解决C#向C++DLL传递 struct数组时产生的数据丢失问题?

问题描述

如何解决C#向C++DLL传递 struct数组时产生的数据丢失问题?

运行环境:win8.1+vs2010

目的:将C#中的结构体数组传到C++的动态链接库中

代码:

//DLL中的接口,C++
  struct Target
  {
    int ID;
    double PosX
    double PosY;
    float Aangle;
    long EncoderValue;
  };
  class Backstage
  {
      EXTERN_C BACKSTAGE_API int WINAPI Allocater_AddNewTargets(Target *targets,int num);
  }
//使用DLL的c#代码
  [StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
  public struct Target
  {
      public int ID;
      public double PosX;
      public double PosY;
      public float Aangle;
      public long EncoderValue;
  };
  private void button1_Click(object sender, RoutedEventArgs e)
  {
      Target[] targets = new Target[4];
      targets[0].Aangle = 12.1F;
      targets[0].EncoderValue = 0;
      targets[0].ID = 10;
      targets[0].PosX = 12.4;
      targets[0].PosY = 123.22;
      unsafe
      {
          fixed (Target* p = targets)
          {
              Backstage.Allocater_AddNewTargets(p, targets.Length);
          }
       }
   }

问题描述:当调用函数时马上出现结构体数据被刷掉的情况。断点在进入Allocater_AddNewTargets的前一句代码,结构体中的数据还是正确的。断点在Allocater_AddNewTargets中的第一句代码,发现结构体的数据已经被刷掉了。
注意:结构体地址被正确传送,甚至结构体内的每一个变量的地址也正确

尝试:

1、在C#中用IntPtr开辟非托管内存块储存结构体,并用IntPtr作为参数,还是一样的情况,**结构体数据被刷掉**。

2、把C#结构体的[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]特性去掉,**结构体数据正确,但出现内存边界对齐问题。**C++的结构体是4字符对齐,C#的结构体是8字符对齐。

3、把C#结构体的[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]特性去掉,改为在C++中用#pragma pack(1)改变C++结构体的对齐方式,结果还是**结构体数据被刷掉**。

解决方案

C++的long还是32位的,C#是64位的。

解决方案二:

结构体中成员定义写成类似这样的
struct XXX
{
[MarshalAs(UnmanagedType.I4)]
public int index;
...
}

时间: 2024-10-18 13:06:08

内存管理-如何解决C#向C++DLL传递 struct数组时产生的数据丢失问题?的相关文章

cocos2dx 内存管理

cocos2dx的内存管理移植自Objective-C, 对于没有接触过OC的C++开发人员来说是挺迷惑的.不深入理解内存管理是无法写出好的C++程序的,我用OC和cocos2dx也有一段时间了,在此总结一下,希望对想用cocos2dx开发游戏的朋友有所帮助. C++的动态内存管理一般建议遵循谁申请谁释放的原则,即谁通过new操作符创建了对象,谁就负责通过delete来释放对象.如果对象的生命周期在一个函数内,这很容易做到,在函数返回前delete就行了.但一般我们在函数中new出来的对象的生命

【高质量代码】如何写出更高质量的C/C++代码(1):内存管理

内存的管理是C/C++开发程序过程中的一个比较麻烦的问题.对于经验不是足够丰富的程序员来说,开发比较复杂的程序的时候几乎肯定会遇到内存管理方面的bug.对C/C++语言以及编译机制深入的理解和养成良好的编程习惯可以尽量减少这类bug产生的几率. 1.C/C++程序运行时内存结构简介 一个典型的C/C++编译的进程所占用的内存空间通常分为5个部分,由低地址到高地址分别为: 代码段(Code/Text Segment):保存可执行程序运行的二进制代码段. 数据段(Data Segment):保存进程

IOS中内存管理那些事_IOS

Objective-C 和 Swift 语言的内存管理方式都是基于引用计数「Reference Counting」的,引用计数是一个简单而有效管理对象生命周期的方式.引用计数分为手动引用计数「ARC: AutomaticReference Counting」和自动引用计数「MRC: Manual Reference Counting」,现在都是用 ARC 了,但是我们还是很有必要了解 MRC. 1. 引用计数的原理是什么? 当我们创建一个新对象时,他的引用计数为1: 当有一个新的指针指向这个对象

理解iOS的内存管理

远古时代的故事 那些经历过手工管理内存(MRC)时代的人们,一定对 iOS 开发中的内存管理记忆犹新.那个时候大约是 2010 年,国内 iOS 开发刚刚兴起,tinyfool 大叔的大名已经如雷贯耳,而我还是一个默默无闻的刚毕业的小子.那个时候的 iOS 开发过程是这样的: 我们先写好一段 iOS 的代码,然后屏住呼吸,开始运行它,不出所料,它崩溃了.在 MRC 时代,即使是最牛逼的 iOS 开发者,也不能保证一次性就写出完美的内存管理代码.于是,我们开始一步一步调试,试着打印出每个怀疑对象的

PHP原理之内存管理中难懂的几个点

PHP的内存管理, 分为俩大部分, 第一部分是PHP自身的内存管理, 这部分主要的内容就是引用计数, 写时复制, 等等面向应用的层面的管理. 而第二部分就是今天我要介绍的, zend_alloc中描写的关于PHP自身的内存管理, 包括它是如何管理可用内存, 如何分配内存等. 另外, 为什么要写这个呢, 因为之前并没有任何资料来介绍PHP内存管理中使用的策略, 数据结构, 或者算法. 而在我们平时开发扩展, 修复PHP的bug的时候, 却对这一部分的知识需要有一个良好的理解. PHP开发组内的很多

Objective-C之集合对象的内存管理

集合对象的内存管理 本小节知识点: [掌握]集合对象的内存管理 [理解]集合对象内存管理总结 1.集合对象的内存管理 当一个对象加入到集合中,那么该对象的引用计数会+1 当集合被销毁的时候,集合会向集合中的元素发送release消息 NSMutableArray *arr = [[NSMutableArray alloc] init]; Person *p = [[Person alloc] init]; NSLog(@"retainCount = %lu", [p retainCou

linux内存管理-内核用户空间 【转】

转自:http://blog.chinaunix.net/uid-25909619-id-4491362.html 1,linux内存管理中几个重要的结构体和数组 page unsigned long flags 一组标志,也对页框所在的管理区进行编号 atomic_t _count 该页被引用的次数 atomic_t _mapcount 页框中页表项数目,如果没有则为-1 struct list_head lru 管理page忙碌/空闲链表(inactive_list/active_list)

iOS/OS X 内存管理(二):借助工具解决内存问题

上一篇博客iOS/OS X内存管理(一):基本概念与原理主要讲了iOS/OSX 内存管理中引用计数和内存管理规则,以及引入ARC新的内存管理机制之后如何选择ownership qualifiers(__strong.__weak.__unsafe_unretained和__autoreleasing)来管理内存.这篇我们主要关注在实际开发中会遇到哪些内存管理问题,以及如何使用工具来调试和解决. 在往下看之前请下载实例MemoryProblems,我们将以这个工程展开如何检查和解决内存问题. 悬挂

深入SQL SERVER 2000的内存管理机制(二)

server 深入SQL SERVER 2000的内存管理机制(二)     http://msdn.microsoft.com/data/default.aspx?pull=/library/en-us/dnsqldev/html/sqldev_01262004.asp   可访问大地址的应用 (Large-Address-Aware Executables) 在Windows增加支持/3GB参数以前,一个应用程序是无法访问一个带有高位设置的指针.一个32位的指针只有前31位地址空间可以被用户