如何巧妙获取genius_platform软件平台开发中结构体数据成员的偏移量?

2026-04-11 21:211阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计839个文字,预计阅读时间需要4分钟。

如何巧妙获取genius_platform软件平台开发中结构体数据成员的偏移量?

今天项目中需要计算结构体数据的成员偏移量,可使用底层方法巧妙获取,注意区分数据成员的赋值操作。

今天在项目中需要使用到结构体数据成员的偏移量计算,可以使用下面的方法来进行巧妙的获取,注意区别数据成员的赋值操作哦;

# 1. 结构体指针为0时,数据成员赋值会内存访问崩溃

# 2. 结构体指针为0时,数据成员可以内存访问并计算偏移量

- 源代码:


```cpp


#include "stdafx.h"


#if defined (BUILD_AMBARELLA_AMBACV_DRV) && defined (BUILD_AMBARELLA_CAVALRY_DRV)

#error "Can not enable ambacv and cavalry at the same time"

如何巧妙获取genius_platform软件平台开发中结构体数据成员的偏移量?

#elif defined (BUILD_AMBARELLA_AMBACV_DRV)

#define CAVALRY_DEV_NODE "/dev/ambacv"

#else

#define CAVALRY_DEV_NODE "/dev/cavalry"

#endif



typedef struct

{

int nHasMm2S; /* Has transmit channel */

int nHasS2Mm; /* Has receive channel */

int nInitialized; /* Driver has been initialized */

int nHasSg;

int nTxNumChannels;

int nRxNumChannels;

int nMicroDmaMode;

int nAddrWidth; /**< Address Width */

}stuXAxiDma;


/*****************************************************************************/

/** 1.5 chip common part, audio interface, depend on DMA interface

******************************************************************************/

#define VAROFFSET(type, mem) ((unsigned long)(&((type *)0)->mem))

#define GET_STRUCT_ENTRY(ptr, type, mem) ((type *)((char *)ptr - VAROFFSET(type, mem)))

/*

*callback function

*Check interrupt status and assert s2mm flag

*/

typedef struct

{

int* pBdTxChainBuffer;

int* pBdRxChainBuffer;

int nDmaDevId;

int nS2mmIntrId;

int nMm2sIntrId;

int nBdCount;

char cBdNum; // 注意未对齐32位系统占4个字节

void(*s2mmFinishCb)(void*);

void(*mm2sFinishCb)(void*);

stuXAxiDma axiDma;

}stuChipAudioChannel;


static void dmaInterruptHandler(void* pCallBackRef)

{

// 进行指针转换

stuXAxiDma* pXAxiDmaPtr = (stuXAxiDma *)pCallBackRef;

printf("dmaInterruptHandler::pCallBackRef=[%p]\n", pCallBackRef);


//注意堆的特性,向上生长,地址变小

//stuChipAudioChannel *p_audio_channel = (stuChipAudioChannel *)((char *)ptr - ((int)&((stuChipAudioChannel*)0)->axiDma));

stuChipAudioChannel* pAudioChannel = GET_STRUCT_ENTRY(pCallBackRef, stuChipAudioChannel, axiDma);

printf("dmaInterruptHandler::pAudioChannel=[%p]\n", pAudioChannel);

}



int _tmain(int argc, _TCHAR* argv[])

{

// 申请内存给指针ptr赋值

stuXAxiDma* ptr = new stuXAxiDma();

//指针ptr设置为空((void*)0)

//ptr = NULL;

// 设置指针ptr的数据成员nAddrWidth = 0

ptr->nAddrWidth = 0; // 内存访问会报错

// 只是访问取数据成员变量没问题

int nAddrWidthOffset = (int)&(ptr->nAddrWidth);

// 能够直接取出偏移量来

int nBdTxChainBufferOffset = ((int)(&((stuChipAudioChannel*)0)->pBdTxChainBuffer));

// nBdTxChainBufferOffset=0

printf("_tmain::nBdTxChainBufferOffset=[%d]\n", nBdTxChainBufferOffset);


int nDmaDevIdOffset = ((int)(&((stuChipAudioChannel*)0)->nDmaDevId));

printf("_tmain::nDmaDevIdOffset=[%d]\n", nDmaDevIdOffset);


int nS2mmFinishCbOffset = ((int)(&((stuChipAudioChannel*)0)->s2mmFinishCb));

printf("_tmain::nS2mmFinishCbOffset=[%d]\n", nS2mmFinishCbOffset);


int nAxiDmaOffset = ((int)(&((stuChipAudioChannel*)0)->axiDma));

printf("_tmain::nAxiDmaOffset=[%d]\n", nAxiDmaOffset);


// 申请堆内存给pXAxiDma变量

stuXAxiDma* pXAxiDma = new stuXAxiDma;

dmaInterruptHandler(pXAxiDma);

return 0;

}



```


- 输出结果:



# 3. 原理解释:

- 在结构体成员变量前面加上取地址符号&后表示取的是`nAddrWidth`字段的地址,而不是引用该字段内容,因此不会产生段错误。

- 如果`ptr`为空,直接取该成员变量的内容或者更新、设置该内存的值时会发生段错误。

本文共计839个文字,预计阅读时间需要4分钟。

如何巧妙获取genius_platform软件平台开发中结构体数据成员的偏移量?

今天项目中需要计算结构体数据的成员偏移量,可使用底层方法巧妙获取,注意区分数据成员的赋值操作。

今天在项目中需要使用到结构体数据成员的偏移量计算,可以使用下面的方法来进行巧妙的获取,注意区别数据成员的赋值操作哦;

# 1. 结构体指针为0时,数据成员赋值会内存访问崩溃

# 2. 结构体指针为0时,数据成员可以内存访问并计算偏移量

- 源代码:


```cpp


#include "stdafx.h"


#if defined (BUILD_AMBARELLA_AMBACV_DRV) && defined (BUILD_AMBARELLA_CAVALRY_DRV)

#error "Can not enable ambacv and cavalry at the same time"

如何巧妙获取genius_platform软件平台开发中结构体数据成员的偏移量?

#elif defined (BUILD_AMBARELLA_AMBACV_DRV)

#define CAVALRY_DEV_NODE "/dev/ambacv"

#else

#define CAVALRY_DEV_NODE "/dev/cavalry"

#endif



typedef struct

{

int nHasMm2S; /* Has transmit channel */

int nHasS2Mm; /* Has receive channel */

int nInitialized; /* Driver has been initialized */

int nHasSg;

int nTxNumChannels;

int nRxNumChannels;

int nMicroDmaMode;

int nAddrWidth; /**< Address Width */

}stuXAxiDma;


/*****************************************************************************/

/** 1.5 chip common part, audio interface, depend on DMA interface

******************************************************************************/

#define VAROFFSET(type, mem) ((unsigned long)(&((type *)0)->mem))

#define GET_STRUCT_ENTRY(ptr, type, mem) ((type *)((char *)ptr - VAROFFSET(type, mem)))

/*

*callback function

*Check interrupt status and assert s2mm flag

*/

typedef struct

{

int* pBdTxChainBuffer;

int* pBdRxChainBuffer;

int nDmaDevId;

int nS2mmIntrId;

int nMm2sIntrId;

int nBdCount;

char cBdNum; // 注意未对齐32位系统占4个字节

void(*s2mmFinishCb)(void*);

void(*mm2sFinishCb)(void*);

stuXAxiDma axiDma;

}stuChipAudioChannel;


static void dmaInterruptHandler(void* pCallBackRef)

{

// 进行指针转换

stuXAxiDma* pXAxiDmaPtr = (stuXAxiDma *)pCallBackRef;

printf("dmaInterruptHandler::pCallBackRef=[%p]\n", pCallBackRef);


//注意堆的特性,向上生长,地址变小

//stuChipAudioChannel *p_audio_channel = (stuChipAudioChannel *)((char *)ptr - ((int)&((stuChipAudioChannel*)0)->axiDma));

stuChipAudioChannel* pAudioChannel = GET_STRUCT_ENTRY(pCallBackRef, stuChipAudioChannel, axiDma);

printf("dmaInterruptHandler::pAudioChannel=[%p]\n", pAudioChannel);

}



int _tmain(int argc, _TCHAR* argv[])

{

// 申请内存给指针ptr赋值

stuXAxiDma* ptr = new stuXAxiDma();

//指针ptr设置为空((void*)0)

//ptr = NULL;

// 设置指针ptr的数据成员nAddrWidth = 0

ptr->nAddrWidth = 0; // 内存访问会报错

// 只是访问取数据成员变量没问题

int nAddrWidthOffset = (int)&(ptr->nAddrWidth);

// 能够直接取出偏移量来

int nBdTxChainBufferOffset = ((int)(&((stuChipAudioChannel*)0)->pBdTxChainBuffer));

// nBdTxChainBufferOffset=0

printf("_tmain::nBdTxChainBufferOffset=[%d]\n", nBdTxChainBufferOffset);


int nDmaDevIdOffset = ((int)(&((stuChipAudioChannel*)0)->nDmaDevId));

printf("_tmain::nDmaDevIdOffset=[%d]\n", nDmaDevIdOffset);


int nS2mmFinishCbOffset = ((int)(&((stuChipAudioChannel*)0)->s2mmFinishCb));

printf("_tmain::nS2mmFinishCbOffset=[%d]\n", nS2mmFinishCbOffset);


int nAxiDmaOffset = ((int)(&((stuChipAudioChannel*)0)->axiDma));

printf("_tmain::nAxiDmaOffset=[%d]\n", nAxiDmaOffset);


// 申请堆内存给pXAxiDma变量

stuXAxiDma* pXAxiDma = new stuXAxiDma;

dmaInterruptHandler(pXAxiDma);

return 0;

}



```


- 输出结果:



# 3. 原理解释:

- 在结构体成员变量前面加上取地址符号&后表示取的是`nAddrWidth`字段的地址,而不是引用该字段内容,因此不会产生段错误。

- 如果`ptr`为空,直接取该成员变量的内容或者更新、设置该内存的值时会发生段错误。