问题描述
我有一个内存分配不正确的问题。我认为是因为位在属性之间转移。
这是本机代码:
typedef struct s_xl_channel_config {
char name [32];
unsigned char hwType;
unsigned char hwIndex;
unsigned char hwChannel;
unsigned short transceiverType;
unsigned short transceiverState;
unsigned short configError;
unsigned char channelIndex;
unsigned __int64 channelMask;
unsigned int channelCapabilities;
unsigned int channelBusCapabilities;
unsigned char isOnBus;
unsigned int connectedBusType;
XLbusParams busParams;
unsigned int _doNotUse;
unsigned int driverVersion;
unsigned int interfaceVersion;
unsigned int raw_data[10];
unsigned int serialNumber;
unsigned int articleNumber;
char transceiverName [32];
unsigned int specialCabFlags;
unsigned int dominantTimeout;
unsigned char dominantRecessiveDelay;
unsigned char recessiveDominantDelay;
unsigned char connectionInfo;
unsigned char currentlyAvailableTimestamps;
unsigned short minimalSupplyVoltage;
unsigned short maximalSupplyVoltage;
unsigned int maximalBaudrate;
unsigned char fpgaCoreCapabilities;
unsigned char specialDeviceStatus;
unsigned short channelBusActiveCapabilities;
unsigned short breakOffset;
unsigned short delimiterOffset;
unsigned int reserved[3];
} XL_CHANNEL_CONfig;
我的java代码是这样的:
@FieldOrder ({"name","hwType","hwIndex","hwChannel","transceiverType","transceiverState","configError","channelIndex","channelMask","channelCapabilities","channelBusCapabilities","isOnBus","connectedBusType","busParams","_doNotUse","driverVersion","interfaceVersion","raw_data","serialNumber","articleNumber","transceiverName","specialCabFlags","dominantTimeout","dominantRecessiveDelay","recessiveDominantDelay","connectionInfo","currentlyAvailableTimestamps","minimalSupplyVoltage","maximalSupplyVoltage","maximalBaudrate","fpgaCoreCapabilities","specialDeviceStatus","channelBusActiveCapabilities","breakOffset","delimiterOffset","reserved"})
public class XLchannelConfig extends Structure{
public byte[] name = new byte[32];
public byte hwType;
public byte hwIndex;
public byte hwChannel;
public short transceiverType;
public short transceiverState;
public short configError;
public byte channelIndex;
public Nativelong channelMask;
public int channelCapabilities;
public int channelBusCapabilities;
public byte isOnBus;
public int connectedBusType;
public XLbusParams busParams= new XLbusParams();
public int _doNotUse;
public int driverVersion;
public int interfaceVersion;
public int[] raw_data = new int[(10)];
public int serialNumber;
public int articleNumber;
public byte[] transceiverName = new byte[32];
public int specialCabFlags;
public int dominantTimeout;
public byte dominantRecessiveDelay;
public byte recessiveDominantDelay;
public byte connectionInfo;
public byte currentlyAvailableTimestamps;
public short minimalSupplyVoltage;
public short maximalSupplyVoltage;
public int maximalBaudrate;
public byte fpgaCoreCapabilities;
public byte specialDeviceStatus;
public short channelBusActiveCapabilities;
public short breakOffset;
public short delimiterOffset;
public int[] reserved = new int[3];
public XLchannelConfig() {
super();
}
XLchannelConfig类位于我用.toArray()
初始化的数组中。
当我输出属性时,我看到值发生了变化。看起来这些位已从一个属性转移到了另一个属性。我怀疑这是由于数据类型错误造成的,但我无法确定它是哪一个。
toString打印出来:
XLchannelConfig [name=Virtual Channel 1,hwType=1,hwIndex=0,hwChannel=0,transceiverType=0,transceiverState=0,channelIndex=1,channelMask=0,channelCapabilities=458752,channelBusCapabilities=106496,isOnBus=1,connectedBusType=16777216,driverVersion=67830784,interfaceVersion=0,raw_data=[0,65536,0],serialNumber=0,articleNumber=536870912,transceiverName=Virtual CAN,specialCabFlags=0,dominantTimeout=0,reserved=[0,1442840576],busParams=XLbusParams [busType=536870912]]
XLchannelConfig [name=irtual Channel 2,hwType=0,hwIndex=1,hwChannel=22,channelIndex=0,channelCapabilities=1792,channelBusCapabilities=16777632,isOnBus=0,connectedBusType=65536,driverVersion=264964,256,articleNumber=1444937728,transceiverName=irtual CAN,busParams=XLbusParams [busType=-1591738368]]
解决方法
症状表明映射中有一个额外的单字节。 def _configureOutputFilename(self,filename):
"""
generates filename
appends timeseries file extension if necessary
prepends sample directory if used in stochastic
"""
assert not os.path.isabs(filename),filename
if not os.path.splitext(filename)[1]:
filename += ".tss"
if hasattr(self._userModel,"nrSamples"):
filename = os.path.join(str(self._userModel.currentSampleNumber()),filename)
return filename
字段的最后一个元素包括字节reserved
,它对应于第二个元素中缺少的字母“ V”。因此,我们需要寻找额外的字节。
头文件总线类型最多只能达到0x56
。您的输出的总线类型为0x100
,表明错误在0x20000000
联合之前发生。它肯定发生在XLbusParams
之前,后者显示一个额外的非空字节作为最后一个字符。除了transcieverName
(如下所述,偏移量为4个字节)之外,映射看起来是正确的。
一个可能解释单个字节的不匹配可能是结构字段的对齐。名称占用32个字节,然后有3个1字节字段,后跟3个2字节字段。这将使channelMask
字段之一跨越4字节或8字节边界。您可能会考虑使用不同的JNA结构对齐方式,例如Structure.ALIGN_NONE:
short
其他映射注释:
C头中的public XLchannelConfig() {
super(Structure.ALIGN_NONE);
}
字段是显式的64位类型(channelMask
),因此应直接映射到Java的64位int64
。仅当本机类型为long
时,才应使用NativeLong
作为映射。可以是32位,也可以是64位,具体取决于操作系统和位。但是,这可能会分配不足4个字节,这可能不是问题。
在API头文件的副本中,看不到您包含的long
字段。您确定应将其包括在内吗?这会向映射添加4个字节。您确定复制的头文件与您使用的API二进制文件的版本匹配吗?
问题的另一个潜在来源是_doNotUse
类型。 API显示这是一个XLbusParams
类型和32字节数据的联合。如果您未正确映射联合(至少是最大的成员),也可能导致偏移。