函数内初始化结构体指针数组遇malloc错误?Valgrind异常排查
你的问题核心出在new_table函数里分配Table空间时用错了sizeof的参数,我们一步步拆解清楚:
先抓类型定义的关键细节
从test.h的代码里能看到,Table是指针类型的别名:
typedef struct table_s *Table; // Table = 指向struct table_s的指针 struct table_s { int n; Node *arrayOfNodes; };
在64位系统上,指针大小固定是8字节,但struct table_s本身的大小是「int(通常4字节) + 指针(8字节)」,再加上内存对齐,实际占用空间远大于8字节。
为什么第6行的malloc会触发Valgrind错误?
你写的这行代码:
Table thisTable = malloc(sizeof(Table));
这里sizeof(Table)计算的是指针的大小(8字节),但你真正需要分配的是struct table_s结构体本身的空间。这就导致你只拿到了8字节的内存块,而struct table_s需要更大的空间。当你执行thisTable->n = 2;时,相当于往分配的8字节块的外部写数据,这就是Valgrind报告「Invalid write of size 8」的原因——你越界访问了非法内存。
为什么第11行的malloc是正常的?
第11行的代码:
Node *array = malloc(thisTable->n*sizeof(Node));
这里Node虽然也是指针类型(struct node*),但array是Node*(指向指针的指针),你需要分配n个Node指针的空间,所以sizeof(Node)是完全正确的——每个指针占8字节,分配n*8字节正好能放下n个指针,自然不会有越界问题。
修复方法
把第6行的sizeof(Table)改成sizeof(struct table_s),或者更安全的写法sizeof(*thisTable)(因为thisTable是Table类型即struct table_s*,*thisTable就是结构体本身):
修复后的new_table函数:
Table new_table() { Table thisTable = malloc(sizeof(struct table_s)); // 更推荐的写法:malloc(sizeof(*thisTable)); thisTable->n = 2; thisTable->arrayOfNodes = malloc(thisTable->n*sizeof(Node)); Node *array = malloc(thisTable->n*sizeof(Node)); return thisTable; }
用sizeof(*thisTable)的好处是,哪怕以后修改struct table_s的定义或者Table的类型别名,这行代码也不需要改动,能彻底避免同类错误。
修复验证
修改后,Valgrind不会再报告越界错误,大n值的场景也能正常运行——因为你给struct table_s分配了足够的空间,后续对thisTable->n和thisTable->arrayOfNodes的访问都在合法内存范围内。
内容的提问来源于stack exchange,提问作者Hevv

