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

为何指针赋值会导致看似无关的区间值意外变化?

双指针处理区间问题时的意外值变化分析

我尝试用双指针(double pointers)解决区间问题,核心思路是在unordered_map中存储指向Interval结构体的双指针,无需遍历map即可更新区间。但使用双指针时出现了意外的区间值变化:在代码的HERE 1和HERE 2标记之间,(*(it_pre->second))->word的值发生了改变,这段时间我仅创建了一个新的、无关的Interval,无法理解原因。

问题代码

#include <iostream>
#include <vector>
#include <utility>
#include <unordered_map>
using namespace std;

int main()
{
    vector<pair<int, char>> sequence = { 
        {0,'a'},
        {1,'-'},
        {2,'b'},
        {3,'c'},
        {4,'-'},
        {5,'d'},
        {6,'e'},
        {7,'-'},
        {8,'f'},
        {10,'g'},
        {11,'-'},
        {12, '-'}
    };

    struct Interval {
        string word;
        bool startH;
        bool endH;
        Interval(string word) : word(word), startH(false), endH(false) {}

    };

    Interval* hyphen = new Interval("-");
    Interval** hPtr = &hyphen;

    auto consolidate = [&hPtr](Interval**& left, Interval**& right) {
        //cout << "\t(" << (*left)->word << " " << (*right)->word << ")" << endl;
        if (left == hPtr && right == hPtr) return;

        if (left == hPtr) {
            (*right)->startH = true;
        }
        else if (right == hPtr) {
            (*left)->endH = true;
        }
        else {
            (*right)->startH = (*left)->startH;
            (*right)->word = (*left)->word + (*right)->word;
            (*left) = (*right);
        }

        if ((*right)->startH && (*right)->endH) {
            cout << "RESULT: " << (*right)->word << endl;
        }
        else if ((*left)->startH && (*left)->endH) {
            cout << "RESULT: " << (*left)->word << endl;
        }
    };


    unordered_map<int, Interval**> intervals;

    for (auto pair : sequence) {
        int index = pair.first;
        char c = pair.second;
        cout << "----" << index << ", " << c << "-----" << endl;
        
        int preIndex = index - 1;
        int postIndex = index + 1;
        auto it_pre = intervals.find(preIndex);
        auto it_post = intervals.find(postIndex);
        
        //HERE 1
        //if (it_pre != intervals.end()) cout << (*(it_pre->second))->word << endl;
        
        Interval** currentIntervalPtr;

        if (c == '-') {
            currentIntervalPtr = hPtr;
        }
        else {
            Interval* currentInterval = new Interval(string(1, c));
            currentIntervalPtr = &currentInterval;
        }

        //HERE 2
        //if (it_pre != intervals.end()) cout << (*(it_pre->second))->word << endl;

        if (it_pre != intervals.end()) {
            Interval** prePtr = it_pre->second;
            //cout << "PRE: <" << (*currentIntervalPtr)->word << ", " << (*prePtr)->word << ">>" << endl;
            consolidate(prePtr, currentIntervalPtr);
        }

        if (it_post != intervals.end()) {
            Interval** postPtr = it_post->second;
            //cout << "POST: <" << (*currentIntervalPtr)->word << ", " << (*postPtr)->word << ">>" << endl;
            consolidate(currentIntervalPtr, postPtr);
        }
        
        intervals[index] = currentIntervalPtr;
    }

    return 0;
}

问题根源分析

问题出在非'-'字符的处理分支:

else {
    Interval* currentInterval = new Interval(string(1, c));
    currentIntervalPtr = &currentInterval;
}

这里的currentInterval是栈上的局部变量,在for循环的每次迭代中,栈帧会重复使用这块内存空间。当你把&currentInterval(栈变量的地址)存入unordered_map后,下一次迭代创建新的currentInterval时,会直接覆盖这块栈内存,导致之前存在map里的指针指向的内容被意外修改——这就是HERE 1和HERE 2之间值莫名变化的核心原因。

除此之外,这段代码还存在两个严重问题:

  1. 野指针风险:栈变量在迭代结束后会被销毁,map中存储的指针会变成野指针,后续访问会触发未定义行为。
  2. 内存泄漏:new出来的Interval对象没有被释放,会造成内存泄漏。

修复建议

  1. 避免存储栈指针:不要把指向栈变量的指针存入容器,改为在堆上分配指针变量,比如:
else {
    // 在堆上分配指针,避免栈内存覆盖
    Interval** currentIntervalPtr = new Interval*(new Interval(string(1, c)));
}
  1. 简化指针结构:你的场景不需要双指针,直接使用unordered_map<int, Interval*>存储单指针即可,大幅降低复杂度。
  2. 使用智能指针:改用std::unique_ptr或std::shared_ptr管理内存,自动避免内存泄漏和野指针问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 19:40:56