简体   繁体   English

将任意结构存储的 void* 引用传递给函数

[英]Passing void* reference for arbitrary structure storage into functions

I have a cli program that is used for talking to FPGA registers and memory.我有一个用于与 FPGA 寄存器和 memory 通信的 cli 程序。 Depending on the command, you may return a 32 bit registers (which may consist of multiple fields) or it could be as large at 128 Bytes.根据命令,您可能会返回一个 32 位寄存器(可能包含多个字段),也可能是 128 字节。 So what I wanted to do, was malloc 128 bytes globally to hold a returned structure, or hold a structure in preparation for it to be written to the FPGA.所以我想做的是,malloc 全局 128 个字节来保存返回的结构,或者保存一个结构以准备将其写入 FPGA。 (see void *entry_top. (见 void *entry_top.

In the example below, I have a singular Get command that fails with a segmentation fault when attempting to print the value of a field obtained.在下面的示例中,我有一个单数 Get 命令在尝试打印所获得字段的值时失败并出现分段错误。 In GDB, I can see that the address of entry_top does not seem to actually seem to be passed by reference into the io_get_entry function which was the intent.在 GDB 中,我可以看到 entry_top 的地址似乎实际上并没有通过引用传递到 io_get_entry function 中,这是意图。

I tried to make things a bit simpler by just assigning a test value 0x12345678 to entry using a cast of (host_global_size_entry_t*).我试图通过使用 (host_global_size_entry_t*) 的强制转换为条目分配一个测试值 0x12345678 来使事情变得更简单一些。 In this test program, at the main level, I believed I should have been able to cast the void * to (host_global_size_entry_t *) and read the set value correctly in entry_top.在这个测试程序中,在主级别,我相信我应该能够将 void * 转换为 (host_global_size_entry_t *) 并在 entry_top 中正确读取设置值。

Not 100% certain, but the issue seems to be that my memory reference is being passed incorrectly with the usage of &entry_top.不是 100% 确定的,但问题似乎是我的 memory 参考在使用 &entry_top 时被错误地传递。

Can anyone comment as to what I have done wrong relative to passing the void* entry_top reference to multiple levels of functions?任何人都可以评论我在将 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;
}

Both in main and host_global_size_read_entry you take the address of entry_top (resp. entry ) This is a void ** , but C++ will silently convert it to a void * without complaint.mainhost_global_size_read_entry中,您都获取entry_top地址(分别为entry )这是一个void ** ,但 C++ 会默默地将其转换为void *而不会抱怨。

Instead, you should pass entry_top by value, so that host_global_size_read_entry and io_get_entry receive the contents of entry_top , ie the pointer to allocated memory.相反,您应该按值传递entry_top ,以便host_global_size_read_entryio_get_entry接收entry_top的内容,即指向分配的 memory 的指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM