结构体字段排序时触发Memory access error问题求助
结构体字段排序触发内存访问错误的解决
问题现象
对结构体字段做冒泡排序时,程序触发内存访问错误(Speicherzugriffsfehler (Speicherabzug geschrieben)),错误仅出现在以下排序代码段:
x= *mannschaften[i]; *mannschaften[i]=*mannschaften[i+1]; *mannschaften[i+1]=x; vertauscht=1;
怀疑需要用malloc()或calloc()分配内存,但不清楚具体用法,也未找到同类问题的解决方案。
完整代码
#include <stdio.h> #include <string.h> typedef struct { char* nation; int goals_scored; int goals_conceded; } Team; typedef struct { Team* t1; Team* t2; int goals_t1; int goals_t2; }Spiel; void ergebnis_eintragen(Spiel s) { s.t1->goals_scored = s.goals_t1; s.t2->goals_scored = s.goals_t2; s.t1->goals_conceded = s.goals_t2; s.t2->goals_conceded = s.goals_t1; } void ausgabe (Team* mannschaften[8]) { Team x; int m=8; int vertauscht; do { vertauscht=0; for (int i=0;i<8;i++) { if (mannschaften[i]->goals_scored<mannschaften[i+1]->goals_scored) { x= *mannschaften[i]; *mannschaften[i]=*mannschaften[i+1]; *mannschaften[i+1]=x; vertauscht=1; } else if (mannschaften[i]->goals_scored==mannschaften[i+1]->goals_scored||mannschaften[i]->goals_conceded>mannschaften[i+1]->goals_conceded) { x = *mannschaften[i]; *mannschaften[i]=*mannschaften[i+1]; *mannschaften[i+1]=x; vertauscht=1; } } m-=1; } while (m>1 && vertauscht); for (int i=0;i<8;i++) printf("\nNation: %s\nTore: %d\nGegentore: %d\n",mannschaften[i]->nation,mannschaften[i]->goals_scored,mannschaften[i]->goals_conceded); } int main (void) { Team t1={"Kroatien",0,0}; Team t2={"Brasilien",0,0}; Team t3={"Niederlande",0,0}; Team t4={"Argentinien",0,0}; Team t5={"Marokko",0,0}; Team t6={"Portugal",0,0}; Team t7={"England",0,0}; Team t8={"Frankreich",0,0}; Spiel s1={&t1,&t2,5,3}; Spiel s2={&t3,&t4,5,6}; Spiel s3={&t5,&t6,1,0}; Spiel s4={&t7,&t8,1,2}; Spiel s5={&t4,&t1,3,0}; Spiel s6={&t8,&t5,2,0}; Spiel s7={&t1,&t5,2,1}; Spiel s8={&t4,&t8,7,5}; Team* ptr_team[8]; ptr_team[0] = &t1; ptr_team[1] = &t2; ptr_team[2] = &t3; ptr_team[3] = &t4; ptr_team[4] = &t5; ptr_team[5] = &t6; ptr_team[6] = &t7; ptr_team[7] = &t8; ergebnis_eintragen(s1); ergebnis_eintragen(s2); ergebnis_eintragen(s3); ergebnis_eintragen(s4); ergebnis_eintragen(s5); ergebnis_eintragen(s6); ergebnis_eintragen(s7); ergebnis_eintragen(s8); ausgabe(&ptr_team[0]); }
问题原因与解决方案
1. 数组越界触发内存错误
冒泡排序的循环条件for (int i=0;i<8;i++)会让i取值到7,此时访问mannschaften[i+1]即mannschaften[8],超出了指针数组ptr_team的下标范围(合法下标为0-7),直接导致非法内存访问。
修复方法:将循环条件改为for (int i=0;i<m-1;i++),利用冒泡排序每轮确定一个最大元素的特性,逐步缩小循环范围,彻底避免越界。
2. 排序逻辑冗余且不符合规则
原else if条件逻辑混乱:mannschaften[i]->goals_scored==mannschaften[i+1]->goals_scored||mannschaften[i]->goals_conceded>mannschaften[i+1]->goals_conceded会导致只要失球数更大就交换,不管进球数是否相等,不符合常规积分榜排序逻辑(先比进球数,进球数相等时比失球数,失球少的排前)。
修复后的排序逻辑:
if (mannschaften[i]->goals_scored < mannschaften[i+1]->goals_scored) { // 进球数少的向后排 swapTeams(mannschaften, i); vertauscht = 1; } else if (mannschaften[i]->goals_scored == mannschaften[i+1]->goals_scored) { // 进球数相等时,失球数多的向后排 if (mannschaften[i]->goals_conceded > mannschaften[i+1]->goals_conceded) { swapTeams(mannschaften, i); vertauscht = 1; } }
可封装交换函数减少代码冗余:
void swapTeams(Team* teams[8], int i) { Team temp = *teams[i]; *teams[i] = *teams[i+1]; *teams[i+1] = temp; }
3. 内存分配的误解
你的代码不需要malloc()或calloc(),main函数中已在栈上创建8个Team实例,指针数组ptr_team指向这些合法的栈内存,只要不越界访问就不会有问题。
修复后的完整ausgabe函数
void swapTeams(Team* teams[8], int i) { Team temp = *teams[i]; *teams[i] = *teams[i+1]; *teams[i+1] = temp; } void ausgabe (Team* mannschaften[8]) { int m=8; int vertauscht; do { vertauscht=0; for (int i=0;i<m-1;i++) { if (mannschaften[i]->goals_scored < mannschaften[i+1]->goals_scored) { swapTeams(mannschaften, i); vertauscht=1; } else if (mannschaften[i]->goals_scored == mannschaften[i+1]->goals_scored) { if (mannschaften[i]->goals_conceded > mannschaften[i+1]->goals_conceded) { swapTeams(mannschaften, i); vertauscht=1; } } } m-=1; } while (m>1 && vertauscht); for (int i=0;i<8;i++) printf("\nNation: %s\nTore: %d\nGegentore: %d\n",mannschaften[i]->nation,mannschaften[i]->goals_scored,mannschaften[i]->goals_conceded); }
内容的提问来源于stack exchange,提问作者kazimir
相关产品推荐
相关产品推荐

