如何正确传递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
相关产品推荐
相关产品推荐

