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

自定义操作系统调用嵌套数组内成员CDraw函数触发通用保护错误问题

故障排查与修复方案

核心故障原因

  • 数组访问逻辑错误:windows定义为Window* windows[128](元素为Window指针的一维数组),代码中错误以二维数组形式windows[0][openedWindows]访问,直接读写非法内存;子组件数组children存在完全相同的错误,是触发「General Protection Fault」的最直接原因。
  • 类型不匹配+对象切片:数组定义为指针类型,但代码直接存入Window/BaseGuiComponent实例,同时AddComponent方法值传递参数会直接切割子类(Button/Window)的独有成员,后续访问不存在的成员变量直接触发内存访问错误。
  • 子组件索引全局共享:childIndex是全局变量而非BaseGuiComponent的成员变量,所有组件共用同一个子组件计数,添加、遍历子组件时会访问完全不属于当前组件的内存空间。
  • 字符串判断逻辑错误:strcmp函数相等时返回0,现有代码if (strcmp(type,"Window",128))的判断逻辑完全相反,类型匹配时不会执行对应分支,反而会执行错误分支访问不存在的成员(比如Button访问WindowStyle成员)。
  • 空指针/未初始化成员风险:按钮绘制逻辑中直接访问parent->bound和当前对象的bound,若parent为空或bound未初始化,会直接触发非法内存访问。

修复方案

1. 修正窗口数组与相关逻辑

将窗口数组改为存储实例的一维数组,修正所有访问逻辑:

int openedWindows = 0;
Window windows[128]; // 改为存储实例的一维数组,不需要指针

int OpenWindow(Window win) {
    windows[openedWindows] = win; // 去掉错误的[0]前缀
    openedWindows++;
    return openedWindows-1;
};
void CloseWindow(int index) {
    for(int i = index; i < openedWindows-1; i++) { // 修正遍历范围,不用写死127
        windows[i] = windows[i+1];
    }
    openedWindows--;
};
void CloseAllWindows() {
    openedWindows = 0; // 不需要逐个重置,直接重置计数即可
};

/*Draw Windows*/
for(int i = 0; i < openedWindows; i++)
{
    windows[i].Update(); // 去掉错误的[0]前缀
}

2. 修正子组件数组与相关逻辑

将childIndex改为类成员变量,数组改为存储实例的一维数组,修正传参与访问逻辑:

// 类定义内部添加成员变量,删除全局childIndex
class BaseGuiComponent {
    // 其他成员...
    int childIndex = 0;
    BaseGuiComponent children[128]; // 改为实例数组,不需要指针
}

int BaseGuiComponent::AddComponent(BaseGuiComponent baseGuiComponent) {
    children[childIndex] = baseGuiComponent; // 去掉错误的[0]前缀
    childIndex++;
    return childIndex-1;
};
void BaseGuiComponent::RemoveComponent(int index) {
    for(int i = index; i < childIndex-1; i++) { // 修正遍历范围
        children[i] = children[i+1];
    }
    childIndex--;
};
void BaseGuiComponent::ClearComponents() {
    childIndex = 0; // 直接重置计数即可
};

//List components and Update();
void BaseGuiComponent::DrawChildren() {
    for(int i = 0; i < childIndex; i++) {
        children[i].Update(); // 去掉错误的[0]前缀
    }
};

如果需要保留多态特性,可将数组改为存储智能指针/堆分配指针,传递参数改为引用/指针,避免对象切片。

3. 修正绘制逻辑判断

修正strcmp的判断逻辑,添加空指针校验:

void BaseGuiComponent::CDraw() {
    if (strcmp(type,"Window") == 0) { // 相等时返回0,添加等于0的判断
        Draw->DrawWindow(BackColor.GetHexColor(), CPosition.X, CPosition.Y, CSize.Width, CSize.Height, 2, CText, WindowStyle, Draw->GetScreenBounds());
        DrawChildren();
    } else if (strcmp(type,"Button") == 0) { // 同上修正判断逻辑
        // 添加parent非空校验
        if (parent == nullptr) return;
        Draw->FillRect(BackColor.GetHexColor(), CGlobalPosition.X*4, CGlobalPosition.Y, CSize.Width*4, CSize.Height, parent->bound);
        Draw->PRINTAT(ForeColor.GetHexColor(),CText, CGlobalPosition.X + nabs(CSize.Width - svlen(CText))/2,CGlobalPosition.Y + nabs(CSize.Height-16)/2, bound);
    }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 05:57:01