将任意结构存储的 void* 引用传递给函数
Passing void* reference for arbitrary structure storage into functions
我有一个用于与 FPGA 寄存器和内存通信的 cli 程序。根据命令的不同,您可以 return 一个 32 位寄存器(可能包含多个字段)或者它可以达到 128 字节。所以我想做的是全局 malloc 128 字节以保存一个 returned 结构,或者保存一个结构以准备将其写入 FPGA。 (参见 void *entry_top.
在下面的示例中,我有一个单一的 Get 命令在尝试打印获得的字段的值时因分段错误而失败。在 GDB 中,我可以看到 entry_top 的地址似乎实际上并没有通过引用传递到意图的 io_get_entry 函数中。
我试图通过使用 (host_global_size_entry_t*) 的转换将测试值 0x12345678 分配给条目来使事情变得更简单。在这个测试程序中,在主级别,我相信我应该能够将 void * 转换为 (host_global_size_entry_t *) 并在 entry_top.
中正确读取设置值
不是 100% 确定,但问题似乎是我的内存引用在使用 &entry_top 时被错误地传递。
任何人都可以评论我在将 void* entry_top 引用传递给多级函数方面做错了什么吗?
using namespace std;
#include "stdint.h"
#include <stdlib.h>
#include <list>
#include <string.h>
#include <string>
#include <iostream>
#ifndef __KRISTEN_TYPES_H__
#define __KRISTEN_TYPES_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#ifdef PACKED
#undef PACKED
#endif /* PACKED */
#define PACKED __attribute__ ((packed))
#ifdef ALIGNED
#undef ALIGNED
#endif /* ALIGNED */
#define ALIGNED __attribute__ ((aligned (4)))
#ifdef __cplusplus
}
#endif /* __cplusplus */
typedef enum _return_t
{
/* Common codes */
func_ok = 0,
func_failed,
func_invalid,
func_not_done
} return_t;
#endif // __KRISTEN_TYPES_H__
uint32_t host_global_size_offset[1] = {53300};
void *entry_top = malloc(32*sizeof(uint32_t));
uint32_t *field_size = (uint32_t*)malloc(sizeof(uint32_t));
uint32_t* result=(uint32_t*)malloc(64*sizeof(uint32_t));
struct _host_global_size_entry_t {
union {
struct {
uint32_t global_size_field : 32 ; // A generic bit field for this register.
} PACKED;
uint8_t entry[5];
} PACKED;
uint8_t alignment_correction[3];
} PACKED;
typedef struct _host_global_size_entry_t __attribute__ ((aligned (4))) host_global_size_entry_t;
return_t io_get_entry(uint32_t index, void *entry, uint32_t base, uint8_t length) {
uint32_t local_addr = base + (index * length);
((host_global_size_entry_t*) entry)->global_size_field = 0x12345678; // Assign a value that we can see in Main'
// The next line shows that the value was 0x12345678 succesfully
printf("io_get_entry local_addr = %d, length = %d, entry->global_sizefield = 0x%X\n", local_addr, length, ((host_global_size_entry_t*) entry)->global_size_field);
return func_ok;
}
return_t host_global_size_read_entry(uint32_t index, void *entry, uint8_t instance) {
return_t result;
uint32_t base;
uint8_t length;
base = host_global_size_offset[instance];
length = sizeof(host_global_size_entry_t);
result = io_get_entry(index, &entry, base, length);
// The next printf causes a segmentation fault. GDB says that &entry here is not the same as &entry in io_get_entry
printf("host_global_size_read_entry = 0x%X\n", ((host_global_size_entry_t*)entry)->global_size_field);
return result;
}
return_t host_global_size_read_field(char *field, uint32_t *field_size, void *result, void *entry) {
//host_global_size_entry_t *entry;
uint32_t field_s = 0;
if (strcmp("global_size_field", field) == 0) {
field_s = 4;
*(uint32_t *)result = ((host_global_size_entry_t*)entry)->global_size_field;
} else if (field_size != NULL) *field_size = field_s;
*field_size = field_s;
return func_ok;
}
int main (void) {
uint8_t instance = 0;
uint32_t index = 0;
// Pass the address of entry_top global
host_global_size_read_entry(index, &entry_top, instance); // Read entry.
// Cast the result to the structure we expect to be comming back.
printf("main: entry_top->global_sizefield = 0x%X\n", ((host_global_size_entry_t*) entry_top)->global_size_field);
return 0;
}
在 main
和 host_global_size_read_entry
中,您都使用 entry_top
的 地址 (相应 entry
)
这是一个 void **
,但 C++ 会毫无怨言地默默地将它转换为 void *
。
相反,您应该按值传递 entry_top
,以便 host_global_size_read_entry
和 io_get_entry
接收 entry_top
的内容,即指向已分配内存的指针。
我有一个用于与 FPGA 寄存器和内存通信的 cli 程序。根据命令的不同,您可以 return 一个 32 位寄存器(可能包含多个字段)或者它可以达到 128 字节。所以我想做的是全局 malloc 128 字节以保存一个 returned 结构,或者保存一个结构以准备将其写入 FPGA。 (参见 void *entry_top.
在下面的示例中,我有一个单一的 Get 命令在尝试打印获得的字段的值时因分段错误而失败。在 GDB 中,我可以看到 entry_top 的地址似乎实际上并没有通过引用传递到意图的 io_get_entry 函数中。
我试图通过使用 (host_global_size_entry_t*) 的转换将测试值 0x12345678 分配给条目来使事情变得更简单。在这个测试程序中,在主级别,我相信我应该能够将 void * 转换为 (host_global_size_entry_t *) 并在 entry_top.
中正确读取设置值不是 100% 确定,但问题似乎是我的内存引用在使用 &entry_top 时被错误地传递。
任何人都可以评论我在将 void* entry_top 引用传递给多级函数方面做错了什么吗?
using namespace std;
#include "stdint.h"
#include <stdlib.h>
#include <list>
#include <string.h>
#include <string>
#include <iostream>
#ifndef __KRISTEN_TYPES_H__
#define __KRISTEN_TYPES_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#ifdef PACKED
#undef PACKED
#endif /* PACKED */
#define PACKED __attribute__ ((packed))
#ifdef ALIGNED
#undef ALIGNED
#endif /* ALIGNED */
#define ALIGNED __attribute__ ((aligned (4)))
#ifdef __cplusplus
}
#endif /* __cplusplus */
typedef enum _return_t
{
/* Common codes */
func_ok = 0,
func_failed,
func_invalid,
func_not_done
} return_t;
#endif // __KRISTEN_TYPES_H__
uint32_t host_global_size_offset[1] = {53300};
void *entry_top = malloc(32*sizeof(uint32_t));
uint32_t *field_size = (uint32_t*)malloc(sizeof(uint32_t));
uint32_t* result=(uint32_t*)malloc(64*sizeof(uint32_t));
struct _host_global_size_entry_t {
union {
struct {
uint32_t global_size_field : 32 ; // A generic bit field for this register.
} PACKED;
uint8_t entry[5];
} PACKED;
uint8_t alignment_correction[3];
} PACKED;
typedef struct _host_global_size_entry_t __attribute__ ((aligned (4))) host_global_size_entry_t;
return_t io_get_entry(uint32_t index, void *entry, uint32_t base, uint8_t length) {
uint32_t local_addr = base + (index * length);
((host_global_size_entry_t*) entry)->global_size_field = 0x12345678; // Assign a value that we can see in Main'
// The next line shows that the value was 0x12345678 succesfully
printf("io_get_entry local_addr = %d, length = %d, entry->global_sizefield = 0x%X\n", local_addr, length, ((host_global_size_entry_t*) entry)->global_size_field);
return func_ok;
}
return_t host_global_size_read_entry(uint32_t index, void *entry, uint8_t instance) {
return_t result;
uint32_t base;
uint8_t length;
base = host_global_size_offset[instance];
length = sizeof(host_global_size_entry_t);
result = io_get_entry(index, &entry, base, length);
// The next printf causes a segmentation fault. GDB says that &entry here is not the same as &entry in io_get_entry
printf("host_global_size_read_entry = 0x%X\n", ((host_global_size_entry_t*)entry)->global_size_field);
return result;
}
return_t host_global_size_read_field(char *field, uint32_t *field_size, void *result, void *entry) {
//host_global_size_entry_t *entry;
uint32_t field_s = 0;
if (strcmp("global_size_field", field) == 0) {
field_s = 4;
*(uint32_t *)result = ((host_global_size_entry_t*)entry)->global_size_field;
} else if (field_size != NULL) *field_size = field_s;
*field_size = field_s;
return func_ok;
}
int main (void) {
uint8_t instance = 0;
uint32_t index = 0;
// Pass the address of entry_top global
host_global_size_read_entry(index, &entry_top, instance); // Read entry.
// Cast the result to the structure we expect to be comming back.
printf("main: entry_top->global_sizefield = 0x%X\n", ((host_global_size_entry_t*) entry_top)->global_size_field);
return 0;
}
在 main
和 host_global_size_read_entry
中,您都使用 entry_top
的 地址 (相应 entry
)
这是一个 void **
,但 C++ 会毫无怨言地默默地将它转换为 void *
。
相反,您应该按值传递 entry_top
,以便 host_global_size_read_entry
和 io_get_entry
接收 entry_top
的内容,即指向已分配内存的指针。