结构体初始化异常:seldata前三个成员值错误的技术问询
问题根源与修复方案
核心错误分析
你的代码存在三处内存相关问题,其中**data指针的内存分配大小不足**是导致seldata前三个元素异常的直接原因:
data内存分配大小错误screen->data=(char**)malloc((screen->datsize));data是char**类型,需要存储7个char*指针,每个指针在64位系统占8字节,总共需要7*8=56字节,但你只分配了7字节。后续执行memcpy(screen->data,HOME_SCREEN,sizeof(HOME_SCREEN))时,会向这7字节空间写入56字节数据,直接触发堆内存越界,溢出内容会覆盖紧接在data内存块后的seldata指针数组。seldata内存分配的类型不匹配screen->seldata=(uint8_t**)malloc(screen->selsize*sizeof(uint8_t**));seldata是uint8_t**类型,每个元素是uint8_t*指针,应该用sizeof(uint8_t*)计算分配大小。虽然64位系统中uint8_t*和uint8_t**大小相同,但这是不规范写法,易在其他环境出错。memcpy字节数写法不严谨memcpy(screen->seldata[i],HOME_SEL[i],3);虽然
uint8_t占1字节,3字节是正确的,但写成3*sizeof(uint8_t)更规范,能避免后续类型调整时出错。
现象解释
- 函数内打印
seldata[0][0]正确:因为你在memcpy(data)之前就完成了seldata的初始化并打印,此时seldata的指针数组还未被越界的memcpy破坏。 - main中
seldata[0][0]输出52:越界的memcpy把HOME_SCREEN里的字符串指针覆盖到了seldata的前几个位置,seldata[0]变成了字符串"4.DISP"的地址,访问[0]就是取该字符串的第一个字符'4',其ASCII值为52。 - 后三个
seldata元素正常:属于堆内存分配的巧合,溢出的字节刚好没覆盖到后三个指针的位置。
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #define START_COL 2 #define MID_COL 30 typedef struct{ int datsize; int selsize; char** data; uint8_t** seldata; }Screen; static const char* HOME_SCREEN[7]={"Ruthless RFID","1.READ CARD","2.WRITE CARD","3.SHOW FILES","4.DISP","5.STATS","6.EXIT"}; static const uint8_t HOME_SEL[6][3]={{2,START_COL,2},{4,START_COL,2},{6,START_COL,2},{2,MID_COL+15,2},{4,MID_COL+15,2},{6,MID_COL+15,2}}; void SCREEN_INIT(Screen* screen){ screen->datsize=7; screen->selsize=6; // 修正data的内存分配大小 screen->data=(char**)malloc(screen->datsize * sizeof(char*)); // 修正seldata的分配类型 screen->seldata=(uint8_t**)malloc(screen->selsize * sizeof(uint8_t*)); for(int i=0;i<screen->selsize;i++){ screen->seldata[i]=(uint8_t*)malloc(3*sizeof(uint8_t)); // 规范memcpy的字节数写法 memcpy(screen->seldata[i],HOME_SEL[i],3 * sizeof(uint8_t)); } memcpy(screen->data,HOME_SCREEN,sizeof(HOME_SCREEN)); } int main(){ Screen HOME; SCREEN_INIT(&HOME); printf("%i\n",HOME.seldata[0][0]); // 现在会输出预期的2 }
内容的提问来源于stack exchange,提问作者Swiss Gnome
相关产品推荐
相关产品推荐

