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

在C++结构体中定义动态数组以避免段错误的技术咨询

修复C++结构体中动态数组的段错误及实现类似vector的功能

核心问题分析

  • Node构造函数无限递归:Node默认构造函数中children = new Node[children_link_Size];会创建149个Node实例,每个实例又会调用默认构造函数再次创建数组,无限递归直接触发栈溢出(段错误的核心原因)。
  • 全局变量引发数组越界:itemListIndex、freqIdx等全局变量被所有对象共享,多对象操作时索引会超出数组边界,导致段错误。
  • 裸指针内存管理混乱:手动用new/delete管理数组,缺少拷贝构造与赋值运算符重载,会引发浅拷贝、重复释放内存;部分代码对空指针执行无效操作(如ordered初始化为nullptr却访问其成员)。
  • 无效逻辑与野指针:operator<<中NoDe是nullptr,代码块永远不会执行;construct中创建pNode后立刻delete,却继续使用该指针,形成野指针。

分步修复方案

1. 解决Node的无限递归问题

将Node中的动态数组替换为vector<Node>,利用vector自动管理内存,彻底避免手动new导致的递归创建:

#include <vector> // 需添加头文件

#define children_link_Size 149
#define row 15
#define col 100

struct Node
{
    int itemValue{};
    int order{ 0 };
    int freq{ 0 };
    Node* parent{ nullptr };
    vector<Node> children;
    vector<Node> links;

    // 默认构造函数初始化vector大小
    Node() : children(children_link_Size), links(children_link_Size) {}

    explicit Node(int const& p_value, int p_order = 0) :itemValue(p_value), order(p_order)
    {
        ++freq;
        cout << " + " << itemValue << " (" << order << ")" << endl;
    }

    bool operator ==(Node const& p_node) const
    {
        return itemValue == p_node.itemValue;
    }

    // vector自动管理内存,无需手动析构
    ~Node() = default;
};

2. 替换全局变量为成员变量

把itemListIndex等全局变量移到对应结构体中作为成员,确保每个对象的状态独立:

struct ItemSupport
{
    explicit ItemSupport(int p_minSup) : minSup(p_minSup), itemListIndex(0), Itemset(row), OrderedItems(row) {}

    vector<Node> Itemset;
    vector<Node> OrderedItems;
    int itemListIndex; // 替换全局变量为成员
    static int minSup;

    // ... 其他代码
};

3. 用vector替代所有手动动态数组

vector自动处理内存分配、拷贝、析构,完全替代new[]/delete[],从根源上避免内存错误:

ItemSupport& operator<<(int const& p_itemValue)
{
    static int order = 0;
    auto inode = find_if(Itemset.begin(), Itemset.end(), [&p_itemValue](Node const& p_node)
    {
        return p_node.itemValue == p_itemValue;
    });

    if (inode == Itemset.end())
    {
        Node node(p_itemValue, order);
        Itemset[itemListIndex] = node;
        itemListIndex++;
        ++order;
    }
    else
    {
        auto& node = const_cast<Node&>(*inode);
        ++node.freq;
    }
    return *this;
}

Node* getItem(int const& p_itemValue)
{
    auto inode = find_if(Itemset.begin(), Itemset.end(), [&p_itemValue](Node const& p_node)
        {
            return p_node.itemValue == p_itemValue;
        });
    if (inode != Itemset.end())
    {
        return const_cast<Node*>(&(*inode));
    }
    return nullptr;
}

4. 修复FP_Tree的无效逻辑与野指针

将ordered空指针改为局部vector存储有序项,删除无效的指针释放操作:

void construct(int *p_itemValues)
{
    // A. 筛选并排序频繁项
    vector<Node> orderedItems;
    for (int i = 0; i < row; ++i)
    {
        int itemValue = p_itemValues[i];
        Node* pNode = _headItemSupport.getItem(itemValue);
        if (pNode && pNode->freq >= ItemSupport::minSup)
        {
            orderedItems.push_back(*pNode);
        }
    }

    // B. 构建FP树
    Node* actualNode = _root;
    string tab;

    for (Node const& node : orderedItems)
    {
        tab += "\t-";
        auto it = find_if(actualNode->children.begin(), actualNode->children.end(),
            [&node](Node const& nodeTmp) {
                return node == nodeTmp;
            });

        if (it != actualNode->children.end())
        {
            actualNode = &(*it);
            ++actualNode->freq;
        }
        else
        {
            Node newNode(node.itemValue);
            newNode.parent = actualNode;
            actualNode->children.push_back(newNode);
            actualNode = &actualNode->children.back();
            
            Node* pNodeHead = _headItemSupport.getItem(node.itemValue);
            if (pNodeHead)
            {
                pNodeHead->links.push_back(*actualNode);
            }
        }
    }
}

5. 修复ostream运算符的无效逻辑

friend ostream& operator<<(ostream& p_os, ItemSupport const& p_itemSupport)
{
    vector<Node> frequentItems = p_itemSupport.getFrequentItems();
    for (Node const& node : frequentItems)
    {
        if (node.itemValue != 0) // 过滤默认构造的空节点
        {
            p_os << node.itemValue << ": support " << node.freq << ", order " << node.order << endl;
        }
    }
    return p_os;
}

// 修改getFrequentItems返回vector
vector<Node> getFrequentItems() const
{
    vector<Node> result;
    for (Node const& item : Itemset)
    {
        if (item.freq >= minSup && item.itemValue != 0)
            result.push_back(item);
    }
    return result;
}

关键注意事项

  • 优先使用vector:vector自动处理内存,完全满足你“类似vector正常工作”的需求,避免手动管理数组的所有风险。
  • 杜绝全局变量:全局变量会破坏对象的独立性,改用成员变量保证每个实例的状态隔离。
  • 空指针检查:访问指针成员前必须确认指针有效,避免无效操作。
  • 遵循RAII原则:利用C++自动资源管理机制(vector、智能指针),减少手动new/delete的使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 04:25:22