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

移植C# icosphere代码到C后出现栈溢出(0xC000001D)的原因

问题背景

参考生成icosphere的文章将C#代码移植到C语言后,运行出现错误:Process returned -1073741795 (0xC000001D) execution time : 8.057 s Press any key to continue.,相关代码片段如下:

#include <stdio.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>

typedef struct Point3D{
    double x;
    double y;
    double z;
} point3D;

typedef struct Triangleindices{
    int v1;
    int v2;
    int v3;
} triangles;

typedef struct MeshGeometry3D{
    point3D *positions;
    int *triangle_indices;
} mesh_geometry;

typedef struct IcosphereCreator{
    mesh_geometry geometry;
    int index;
    int *cache;
} icosphere;

int add_vertex(icosphere* creator, point3D p){
    double length = sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
    creator->geometry.positions[creator->index].x = p.x / length;
    creator->geometry.positions[creator->index].y = p.y / length;
    creator->geometry.positions[creator->index].z = p.z / length;
    return creator->index++;
}

int get_middle_point(icosphere* creator, int p1, int p2){
    bool first_is_smaller = p1 < p2;
    int64_t smaller_index = first_is_smaller ? p1 : p2;
    int64_t greater_index = first_is_smaller ? p2 : p1;
    int64_t key = (smaller_index << 32) + greater_index;
    if (creator->cache[key] != 0)
    {
        return creator->cache[key];
    }
    point3D point1 = creator->geometry.positions[p1];
    point3D point2 = creator->geometry.positions[p2];
    point3D middle;
    middle.x = (point1.x + point2.x) / 2.0;
    middle.y = (point1.y + point2.y) / 2.0;
    middle.z = (point1.z + point2.z) / 2.0;
    int i = add_vertex(creator, middle);
    return i;
}

mesh_geometry create_icosphere(icosphere* creator, int subdivide){
    int max_triangles = 20 * (1 << (2 * subdivide));
    long long unsigned int array_size = max_triangles * sizeof(triangles);
    creator->geometry = (mesh_geometry){0};
    mesh_geometry result = (mesh_geometry){0};
    creator->index = 0;
    point3D p1 = {-1, (1.0 + sqrt(5.0)) / 2.0, 0};
    point3D p2 = {1, (1.0 + sqrt(5.0)) / 2.0, 0};
    point3D p3 = {-1, -(1.0 + sqrt(5.0)) / 2.0, 0};
    point3D p4 = {1, -(1.0 + sqrt(5.0)) / 2.0, 0};
    point3D p5 = {0, -1, (1.0 + sqrt(5.0)) / 2.0};
    point3D p6 = {0, 1, (1.0 + sqrt(5.0)) / 2.0};
    point3D p7 = {0, -1, -(1.0 + sqrt(5.0)) / 2.0};
    point3D p8 = {0, 1, -(1.0 + sqrt(5.0)) / 2.0};
    point3D p9 = {(1.0 + sqrt(5.0)) / 2.0, 0, -1};
    point3D p10 = {(1.0 + sqrt(5.0)) / 2.0, 0, 1};
    point3D p11 = {(1.0 + sqrt(5.0)) / 2.0, 0 -1};
    point3D p12 = {(1.0 + sqrt(5.0)) / 2.0, 0, 1};
    add_vertex(creator, p1);
    add_vertex(creator, p2);
    add_vertex(creator, p3);
    add_vertex(creator, p4);
    add_vertex(creator, p5);
    add_vertex(creator, p6);
    add_vertex(creator, p7);
    add_vertex(creator, p8);
    add_vertex(creator, p9);
    add_vertex(creator, p10);
    add_vertex(creator, p11);
    add_vertex(creator, p12);
    triangles faces[] =
    {
        {0, 11, 5}, {0, 5, 1}, {0, 1, 7}, {0, 7, 10}, {0, 10, 11},
        {1, 5, 9}, {5, 11, 4}, {11, 10, 2}, {10, 7, 6}, {7, 1, 8},
        {3, 9, 4}, {3, 4, 2}, {3, 2, 6}, {3, 6, 8}, {3, 8, 9},
        {4, 9, 5}, {2, 4, 11}, {6, 2, 10}, {8, 6, 7}, {9, 8, 1}
    };
    for (int i = 0; i < subdivide; i++)
    {
        triangles new_faces[array_size];
        int new_faces_index = 0;
        for (int j = 0; j < 20; j++)
        {
            triangles tri = faces[j];
            int a = get_middle_point(creator, tri.v1, tri.v2);
            int b = get_middle_point(creator, tri.v2, tri.v3);
            int c = get_middle_point(creator, tri.v3, tri.v1);
            new_faces[new_faces_index++] = (triangles){tri.v1, a, c};
            new_faces[new_faces_index++] = (triangles){tri.v2, b, a};
            new_faces[new_faces_index++] = (triangles){tri.v3, c, b};
            new_faces[new_faces_index++] = (triangles){a, b, c};
        }
        for (int j = 0; j < new_faces_index; j++)
        {
            faces[j] = new_faces[j];
        }
        for (int i = 0; i < 20; i++)
        {
            triangles tri = faces[i];
            result.triangle_indices[i * 3] = tri.v1;
            result.triangle_indices[i * 3 + 1] = tri.v2;
            result.triangle_indices[i * 3 + 2] = tri.v3;
        }
    }
    return result;
}

int main(void){
    icosphere creator;
    creator.index = -1;
    int subdivision_level = 3;
    creator.geometry = create_icosphere(&creator, subdivision_level);
    for (int i = 0; i < creator.index; i++)
    {
        printf("Vertex %d: (%f, %f, %f)\n", i, creator.geometry.positions[i].x, creator.geometry.positions[i].y, creator.geometry.positions[i].z);
    }
    for (int i = 0; i < creator.index; i += 3)
    {
        printf("Triangle %d: %d, %d, %d\n", i / 3, creator.geometry.triangle_indices[i], creator.geometry.triangle_indices[i + 1], creator.geometry.triangle_indices[i + 2]);
    }
    int count = creator.geometry.triangle_indices;
    return 0;
}
栈溢出错误原因分析

错误码0xC000001D对应栈溢出,核心问题出在栈内存滥用和未初始化指针的非法访问,具体如下:

1. 栈上分配超大可变长度数组(VLA)

在create_icosphere的细分循环中,直接在栈上声明了triangles new_faces[array_size];:

triangles new_faces[array_size];

当细分等级为3时,max_triangles = 20 * (1 << (2*3)) = 1280,array_size = 1280 * sizeof(triangles)(每个triangles占12字节,总大小约15KB)。虽然这个数值看起来不大,但栈的默认空间通常只有1-8MB,且细分等级每提升1,数组大小会翻4倍(比如等级4时达到64KB),直接耗尽栈空间。

C语言中栈内存有限,这种动态大小的数组绝对不能放在栈上,必须改用堆内存(malloc/free)分配。

2. 未初始化指针的非法内存访问

  • icosphere结构体中的cache指针从未分配内存,直接在get_middle_point中访问creator->cache[key]会访问随机非法内存地址,可能直接触发崩溃,或覆盖栈上其他数据破坏栈完整性。
  • mesh_geometry中的positions和triangle_indices都是野指针,add_vertex中直接写入creator->geometry.positions[creator->index]会随机覆盖内存(包括栈内存),最终引发栈溢出。

3. 加剧内存问题的其他错误

  • 循环变量重定义:细分循环的外层变量i和内层的for (int i = 0; i < 20; i++)重名,会导致逻辑混乱,可能错误修改循环计数器,引发更多内存越界。
  • 顶点定义错误:p11 = {(1.0 + sqrt(5.0)) / 2.0, 0 -1};缺少逗号,应为{(1.0 + sqrt(5.0)) / 2.0, 0, -1};,会导致顶点数据错误,间接引发后续内存访问异常。
  • 类型错误赋值:main函数中int count = creator.geometry.triangle_indices;将指针类型赋值给int,属于类型错误,可能导致后续非法内存访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 10:44:53