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

C++程序崩溃排查:私有static map通过静态函数访问异常

问题分析与解决方案

你的程序崩溃的核心原因是静态成员函数frequencies()返回了map的副本而非引用,导致迭代器指向了已经销毁的临时对象,触发了未定义行为(崩溃)。

为什么会崩溃?

当你在main里写:

for (map<string, int>::const_iterator is=TourPackage::frequencies().begin(); is!=TourPackage::frequencies().end();is++)

每次调用TourPackage::frequencies()都会返回一个frequency静态map的临时副本。第一个调用生成的副本在is初始化完成后就会被销毁,is变成了悬空迭代器;后续循环中访问is->first/is->second时,你实际上在访问已经被释放的内存,程序自然崩溃。

而当frequency设为public时,你直接访问的是全局静态的map对象,迭代器指向的是一直存在的对象,所以不会有问题。

修复方案:返回map的引用

要保持frequency的私有性,只需要修改frequencies()函数,让它返回原静态map的引用(最好是const引用,避免外部意外修改):

修改TourPackage.h中的frequencies()函数:

// 改为返回const引用,确保外部只能读取不能修改
static const map<string, int>& frequencies() { return frequency; }

对应的,main中的迭代器可以保持const_iterator,或者用auto简化写法(C++11及以上支持):

// 用范围for循环更安全简洁
for (const auto& pair : TourPackage::frequencies()) {
    cout << pair.first << " " << pair.second << " ";
}

完整修改后的关键代码片段

TourPackage.h

#ifndef TourPackage_H
#define TourPackage_H
#include "Package.h"
#include <vector>
#include <string>
#include <iostream>
#include <map>
using namespace std;

class TourPackage: public Package {
    vector<string> destinations;
    int length; // 修正原代码的拼写错误:lenght → length
    static map<string, int> frequency;
public:
    TourPackage(double, int length);
    virtual ~TourPackage();
    // 返回const引用,保护私有map不被外部修改
    static const map<string, int>& frequencies() { return frequency; }
protected:
private:
};
#endif

TourPackage.cpp(修正拼写错误)

#include "TourPackage.h"

TourPackage::TourPackage(double price,int n):Package(price), length(n) {
    string x;
    for (int i=0;i<length;i++) {
        getline(cin, x);
        destinations.push_back(x);
        ++frequency[destinations[i]];
    }
}

TourPackage::~TourPackage() {
    //dtor
}

main.cpp(优化循环+修复内存泄漏)

#include <iostream>
#include <vector>
#include <string>
#include "TourPackage.h"
#include <typeinfo>
#include <map>
#include <utility>
#include <algorithm>
using namespace std;

map<string, int> TourPackage::frequency;

bool comp (const pair<string, int> &l, const pair<string, int> &r) {
    if (l.second!=r.second) return l.second>r.second;
    return l.first>r.first;
}

int main() {
    TourPackage p(2,4);
    vector<Package*> Packages;
    Packages.push_back(new Package(1000));
    Packages.push_back(new Package(4234));
    Packages.push_back(new TourPackage(32,3));
    Packages.push_back(new TourPackage(234, 4));
    Packages.push_back(new TourPackage(43, 5));

    // 用范围for循环遍历统计结果
    const auto& freq_map = TourPackage::frequencies();
    for (const auto& entry : freq_map) {
        cout << entry.first << " " << entry.second << " ";
    }
    cout << endl << endl;

    // 释放动态分配的对象,避免内存泄漏
    for (auto pkg : Packages) {
        delete pkg;
    }
    Packages.clear();

    return 0;
}

额外提示

  1. 修正了原代码中lenght的拼写错误,避免潜在逻辑问题;
  2. 添加了动态对象的释放代码,防止内存泄漏;
  3. 范围for循环比手动管理迭代器更安全,也更易读,推荐使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:09:56