【问题标题】:Return a structure that was created within a function?返回在函数中创建的结构?
【发布时间】:2018-05-27 15:24:06
【问题描述】:

如问题所述,是否可以在函数中创建结构,然后在函数退出时返回该结构?由于在调用函数之前不会创建结构,因此我不知道在原型中放入什么作为返回值。任何建议/帮助都会很棒,谢谢。

static void section_to_segment_map(Elf *elf, GElf_Ehdr *ehdr) {

    struct memory_data {
        int phdr_addrs[ehdr->e_phnum][2];
        int section_bounds[ehdr->e_shnum][2];
    } memData;

    for(int phead_cnt = 0; phead_cnt < ehdr->e_phnum; phead_cnt++) {
        GElf_Phdr mem;
        GElf_Phdr *phdr = gelf_getphdr(elf, phead_cnt, &mem);

        memData.phdr_addrs[phead_cnt][1] = phdr->p_vaddr;
        memData.phdr_addrs[phead_cnt][2] = phdr->p_vaddr + phdr->p_memsz;

    }
    printf("Starting and Ending Address Values for Program Segments:\n");
    for(int i = 0; i < ehdr->e_phnum; i++)
       printf("%x --> %x\n", memData.phdr_addrs[i][1], memData.phdr_addrs[i][2]);

    Elf_Scn *scn = NULL;
    for(int shead_cnt = 0; shead_cnt < ehdr->e_shnum; shead_cnt++) {
        scn = elf_getscn(elf, shead_cnt);
        GElf_Shdr shdr_mem;
        GElf_Shdr *shdr = gelf_getshdr(scn, &shdr_mem);

        memData.section_bounds[shead_cnt][1] = shdr->sh_addr;
        memData.section_bounds[shead_cnt][2] = shdr->sh_addr + shdr->sh_size;
    }
    printf("\n");
    printf("Starting and Ending Addresses for Program Sections:\n");
    for(int j = 0; j < ehdr->e_shnum; j++) 
        printf("%x --> %x\n", memData.section_bounds[j][1], memData.section_bounds[j][2]);

    return memData;
}

【问题讨论】:

  • 您为什么要这样做?您的代码使用者将如何在结构上声明变量?
  • 需要返回这两个数组以备将来在程序中使用。
  • 你可以在函数外部声明结构体,或者传递指针或引用作为参数,以便函数可以修改传入的句柄数据
  • 只要在函数外声明结构即可。这会更容易,这也是人们所期望的。
  • 函数可以返回结构类型的值,但返回类型需要在函数声明之前完整声明。目前,您的 struct memory_data 类型仅在函数内完全声明,因此您无法返回它。

标签: c data-structures struct return


【解决方案1】:

首先,为了从你的函数返回一个结构,你需要在函数范围之外声明它,这样其他函数也可以使用它。

/* You can change this size if you wish */
#define PHDR_ADDRESS_SIZE (0xffff)
struct memory_data {

        int phdr_addrs[PHDR_ADDRESS_SIZE][2];
        int section_bounds[PHDR_ADDRESS_SIZE][2];
   } memData;

static void section_to_segment_map(Elf *elf, GElf_Ehdr *ehdr)
{
/* Code... */
}

int main(void)
{
    memData m = {};
}

为了从你的函数中返回一个结构,你有两个主要的选择。

实际返回结构

您需要将函数的返回值更改为“memData”类型而不是“void”类型。然后,您可以返回该值。 例如:

memData section_to_segment_map(Elf *elf, GElf_Ehdr *ehdr)
{
    memData m = {};
    /* Code... */
    return m;
}

将输出参数传递给函数

另一个我认为更推荐的选项是将一个 out 参数传递给函数,它是一个指针。

你需要传递一个指向 memData 的指针,你可以在你的函数中改变它。例如:

void section_to_segment_map(Elf *elf, GElf_Ehdr *ehdr, memData* m)
{
    for(int phead_cnt = 0; phead_cnt < ehdr->e_phnum; phead_cnt++) {
        GElf_Phdr mem;
        GElf_Phdr *phdr = gelf_getphdr(elf, phead_cnt, &mem);

        *memData.phdr_addrs[phead_cnt][1] = phdr->p_vaddr;
        *memData.phdr_addrs[phead_cnt][2] = phdr->p_vaddr + phdr->p_memsz;
    }
    /* More of the code.... */
return;
}

为了从 main 调用函数,您应该执行以下操作:

int main(void)
{
    memData m = {};
    /* Put your own arguments isntead of <elf>, <edhr> */
    section_to_segment_map(<elf>, <ehdr>, &m);

}

【讨论】:

  • 阅读以下内容:stackoverflow.com/questions/13645936/…。无论如何,我已经编辑了答案。
  • *memData.phdr_addrs[phead_cnt][1] 正在尝试取消引用 int。也许你的意思是memData-&gt;phdr_addrs[phead_cnt][1]。索引也应该是 0 和 1,而不是 1 和 2(这个错误也在原始代码中)。
  • 您可能在第一个 sn-p 中错过了 typedef
  • @IanAbbott 也许他们的意思是m-&gt;phdr_addrs[phead_cnt][1],因为memData 应该m的参数类型。
  • @Bob__ 是的,我认为 memData 出于某种原因是指针变量(可能是一天结束的疲惫!)。
【解决方案2】:

返回在函数中创建的结构?
是否可以在函数中创建结构,然后返回该结构..?

没有。返回类型必须在函数体之前定义。

// void section_to_segment_map(Elf *elf, GElf_Ehdr *ehdr) {
struct memory_data section_to_segment_map(Elf *elf, GElf_Ehdr *ehdr) {

然而 OP 的 struct 具有可变大小,因此提前定义 struct 失败。

struct memory_data {
    // fails  "error: variably modified 'phdr_addrs' at file scope"
    int phdr_addrs[some_variable][2];  
    ...
} memData;

固定大小的struct 可以工作,但如果很大则可能效率低。

#define MEMORY_DATA_N_MAX 10
struct memory_data {
    int phdr_addrs[MEMORY_DATA_N_MAX][2];  
    ...
} memData;

存在各种动态选项,例如创建包含大小信息和指向已分配空间的指针的struct。这迫使section_to_segment_map() 分配内存,调用者确保它是空闲的。

struct memory_data {
    size_t sz;
    int (*phdr_addrs)[2];
    int (*section_bounds)[2];
} memData;

【讨论】:

    猜你喜欢
    • 2021-06-12
    • 1970-01-01
    • 2018-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多