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

C语言动态Entity结构体数组元素删除异常问题求解

问题:动态数组删除结构体元素时出现乱码与崩溃

问题代码与输出

你提供的代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Entity {
    int x, y;
    int velX, velY;
}Entity;
int remove_element(Entity** array, int sizeOfArray, int indexToRemove) {
    int i;
    printf("Beginning processing. Array is currently: ");
    for (i = 0; i < sizeOfArray; ++i)
        printf("%d ", (*array)[i].x);
    printf("\n");
    Entity* temp = malloc((sizeOfArray - 1) * sizeof(Entity)); // allocate an array with a size 1 less than the current one
    memmove( temp, *array, (indexToRemove+1)*sizeof(Entity)); // copy everything BEFORE the index
    memmove( temp+indexToRemove, (*array)+(indexToRemove+1), (sizeOfArray - indexToRemove)*sizeof(Entity)); // copy everything AFTER the index
    printf("Processing done. Array is currently: ");
    for (i = 0; i < sizeOfArray - 1; ++i)
        printf("%d ", (temp)[i].x);
    printf("\n");
    free (*array);
    *array = temp;
    return 0;
}
int main() {
    int i;
    int howMany = 20;
    Entity* test = malloc(howMany * sizeof(Entity*));
    for (i = 0; i < howMany; ++i)
        (test[i].x) = i;
    remove_element(&test, howMany, 14);
    --howMany;
    return 0;
}

运行后得到的异常输出:

Beginning processing. Array is currently: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Processing done. Array is currently: 0 1 2 3 4 1866386284 6 7 8 9 10 11 12 13 15 16 17 18 19

程序最终在free (*array);行崩溃,预期输出应该是删除索引14后的完整序列。


错误分析与修复方案

1. 内存分配错误(main函数核心问题)

你初始化动态数组时,错误地使用了sizeof(Entity*)而非sizeof(Entity):

Entity* test = malloc(howMany * sizeof(Entity*)); // 错误!

test是指向Entity结构体的指针,每个数组元素是完整的Entity结构体,不是指针类型。用sizeof(Entity*)会导致分配的内存仅为实际需要的1/2或1/4(取决于系统位数),后续的赋值、拷贝操作都会触发内存越界访问,这也是程序free时崩溃的根本原因。

2. memmove拷贝长度计算错误

在remove_element函数中,第二个memmove的拷贝字节数计算有误:

memmove( temp+indexToRemove, (*array)+(indexToRemove+1), (sizeOfArray - indexToRemove)*sizeof(Entity)); // 错误!

要拷贝的是indexToRemove之后的所有元素,元素数量应为sizeOfArray - indexToRemove - 1(总元素数减去要删除的1个,再减去前半部分已拷贝的indexToRemove个)。之前的计算多了一个元素的大小,导致越界读取内存垃圾值,也就是你看到的1866386284。


修正后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Entity {
    int x, y;
    int velX, velY;
} Entity;

int remove_element(Entity** array, int sizeOfArray, int indexToRemove) {
    // 增加非法索引检查
    if (indexToRemove < 0 || indexToRemove >= sizeOfArray) {
        printf("Error: Invalid index to remove!\n");
        return -1;
    }

    int i;
    printf("Beginning processing. Array is currently: ");
    for (i = 0; i < sizeOfArray; ++i)
        printf("%d ", (*array)[i].x);
    printf("\n");

    // 分配新内存,增加分配失败检查
    Entity* temp = malloc((sizeOfArray - 1) * sizeof(Entity));
    if (!temp) {
        perror("Failed to allocate memory");
        return -1;
    }

    // 拷贝前半部分:0 到 indexToRemove-1
    memmove(temp, *array, indexToRemove * sizeof(Entity));
    // 拷贝后半部分:indexToRemove+1 到 sizeOfArray-1
    memmove(temp + indexToRemove, (*array) + indexToRemove + 1, 
            (sizeOfArray - indexToRemove - 1) * sizeof(Entity));

    printf("Processing done. Array is currently: ");
    for (i = 0; i < sizeOfArray - 1; ++i)
        printf("%d ", temp[i].x);
    printf("\n");

    free(*array);
    *array = temp;
    return 0;
}

int main() {
    int i;
    int howMany = 20;
    // 修正内存分配的sizeof参数
    Entity* test = malloc(howMany * sizeof(Entity));
    if (!test) {
        perror("Failed to allocate memory");
        return 1;
    }

    for (i = 0; i < howMany; ++i)
        test[i].x = i;

    // 仅当删除成功时更新数组长度
    if (remove_element(&test, howMany, 14) == 0) {
        --howMany;
    }

    // 最后释放内存,避免泄漏
    free(test);
    return 0;
}

修正后输出

运行代码后会得到预期结果:

Beginning processing. Array is currently: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Processing done. Array is currently: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 15 16 17 18 19

程序也不会再崩溃,同时我还增加了内存分配失败检查、非法索引检查,以及最终的内存释放,提升了代码的健壮性。

内容的提问来源于stack exchange,提问作者Drakalex

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:46:31