You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

结构体字段排序时触发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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 08:15:52