访问结构体数组时抛出异常的问题排查求助
首先看你遇到的异常:
Exception thrown at 0x00577F81 (ucrtbased.dll) in lottery.exe: 0xC0000005: Access violation writing location 0x7B7CC9FC. If there is a handler for this exception, the program may be safely continued.
这通常是非法内存访问导致的,咱们来拆解你代码里的问题:
你的原始代码
#include <stdio.h> #include <stdlib.h> // 补充你未粘贴的player结构体定义(推测合理结构) struct player { char name[50]; int wins; int losses; double funds; double bet; }; void initNames(struct player *p, int size) { int i; for (i = 0; i < size; i++) { printf("Enter player %d's name...\n", (i + 1)); scanf("%s", p[i].name); } return; } void initScore(struct player *p, int size) { int i; for (i = 0; i < size; i++) { p[i].wins = 0; p[i].losses = 0; p[i].funds = 100.00; } return; } void test(struct player *p, int size) { int i; for (i = 0; i < size; i++) { printf("%s, you have $%.2lf. Place your bet!\n", p[i].name, p[i].funds); scanf("%lf", p[i].bet); // 错误点1 } } void main() { int size; struct player *playerPtr; printf("How many players?"); scanf("%d", &size); playerPtr = malloc(sizeof(struct player)*size); initScore(&playerPtr, size); // 错误点2 initNames(&playerPtr, size); // 错误点2 test(&playerPtr, size); // 错误点2 free(playerPtr); }
关键错误点及修复
指针传递类型不匹配
在main里,playerPtr已经是struct player*类型(指向结构体数组的指针),但你调用三个初始化/测试函数时,传递的是&playerPtr——也就是struct player**(指针的指针),和函数要求的struct player*参数类型完全不匹配。这种错误会让函数内部错误解析内存地址,直接导致非法访问。修复:直接传递
playerPtr即可,不需要取地址:initScore(playerPtr, size); initNames(playerPtr, size); test(playerPtr, size);scanf缺少取地址符
test函数里的scanf("%lf", p[i].bet);是典型错误:scanf对于double这类基本类型,必须传入变量的地址,否则它会把输入的值写到p[i].bet当前值对应的内存位置——这个位置几乎肯定是不属于程序的非法内存,触发访问违例。修复:给
p[i].bet加上取地址符&:scanf("%lf", &p[i].bet);main函数返回值不规范
标准C中main的返回类型必须是int而非void,虽然这不是直接引发异常的原因,但不符合语言规范,建议修正:int main() { // ... 原有代码 free(playerPtr); return 0; // 添加返回值 }
修正后的完整代码
#include <stdio.h> #include <stdlib.h> struct player { char name[50]; int wins; int losses; double funds; double bet; }; void initNames(struct player *p, int size) { int i; for (i = 0; i < size; i++) { printf("Enter player %d's name...\n", (i + 1)); scanf("%s", p[i].name); } } void initScore(struct player *p, int size) { int i; for (i = 0; i < size; i++) { p[i].wins = 0; p[i].losses = 0; p[i].funds = 100.00; } } void test(struct player *p, int size) { int i; for (i = 0; i < size; i++) { printf("%s, you have $%.2lf. Place your bet!\n", p[i].name, p[i].funds); scanf("%lf", &p[i].bet); // 修正:添加取地址符 } } int main() { int size; struct player *playerPtr; printf("How many players?"); scanf("%d", &size); playerPtr = malloc(sizeof(struct player)*size); initScore(playerPtr, size); // 修正:直接传递指针 initNames(playerPtr, size); // 修正:直接传递指针 test(playerPtr, size); // 修正:直接传递指针 free(playerPtr); return 0; // 修正:添加返回值 }
修复逻辑说明
- 指针传递修正后,函数能正确访问
playerPtr指向的结构体数组内存,避免地址解析错误; scanf添加取地址符后,输入值会被正确写入到p[i].bet的内存位置,不会触发非法访问;- 修正
main返回值是遵循C标准的健壮性做法。
内容的提问来源于stack exchange,提问作者hax

