You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确传递void指针?结构体指针转void指针返回后取值异常

问题分析与解决方案

哦,我一眼就看到问题出在哪了——你返回了一个局部变量的地址,这直接导致了非法内存访问!

核心错误点

看你HashjoinAllocateDatabase函数里的这行代码:

db = &d;

这里的d是函数内部的局部指针变量,它存储在栈内存中。当函数执行完毕返回后,当前函数的栈帧会被销毁,d所在的内存空间会被标记为无效(后续可能被其他操作覆盖)。此时你返回的&d就是一个指向无效内存的野指针,main函数里把它强制转换成struct database*后访问noOfTuples,自然会得到随机的垃圾值。

正确的写法

你已经通过malloc在堆上分配了struct database的内存空间,d本身就是指向这块堆内存的指针,直接把d赋值给db即可,完全不需要取它的地址:

db = d;

因为HashjoinDatabase是void*类型,struct database*可以隐式转换为void*,语法上完全合法。

优化后的完整代码

另外补充两个小细节:malloc失败时要做完整的错误处理(避免内存泄漏),程序结束后记得释放分配的内存:

#include <stdio.h>
#include <stdlib.h>

typedef void* HashjoinDatabase;

// 补充缺失的结构体定义
struct tuple {
    // 这里添加你的tuple字段
};

struct database {
    struct tuple* tuples;
    int noOfTuples;
};

HashjoinDatabase HashjoinAllocateDatabase(unsigned long totalNumberOfEdgesInTheEnd) {
    struct database* d = malloc(sizeof(struct database));
    if(d == NULL) {
        puts("Some kind of malloc() error");
        return NULL; // 分配失败直接返回NULL
    }
    d->tuples = malloc(totalNumberOfEdgesInTheEnd * sizeof(struct tuple));
    if(d->tuples == NULL) {
        puts("Some kind of malloc() error");
        free(d); // 已经分配的database要释放,避免泄漏
        return NULL;
    }
    d->noOfTuples = 0;
    HashjoinDatabase db = d; // 直接赋值堆指针
    printf("Hello %i\n", d->noOfTuples);
    return db;
}

int main() {
    HashjoinDatabase testDB = HashjoinAllocateDatabase(10);
    if(testDB == NULL) {
        puts("Failed to allocate database");
        return 1;
    }
    int no = ((struct database*)testDB)->noOfTuples;
    printf("Hello %i\n", no);
    
    // 释放堆内存,避免泄漏
    struct database* db = (struct database*)testDB;
    free(db->tuples);
    free(db);
    return 0;
}

修改后,main函数里就能正确读取到noOfTuples的0值了,核心就是要返回堆上分配的结构体指针本身,而不是局部变量的地址。

内容的提问来源于stack exchange,提问作者Ihowa Onaro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 20:57:48