这个 C++ 代码中的段错误在哪里?

问题描述

所以在我包含函数 parse_input 后,我总是收到段错误错误。我尝试了很多东西,但都没有奏效。我当前的代码是:

test.cpp

#include "gtest/gtest.h"
#include "Client.h"
#include "gmock/gmock.h"

using namespace ::testing;

TEST(ClientInputParse,RegularWeekdays) {
    std::vector<Days> days = {Days::Mon,Days::Tues,Days::Wed};
    auto client = Client();
    client.parse_input("Regular: 16Mar2009(mon),17Mar2009(tues),18Mar2009(wed)");
    Client expected(ClientType::Regular,days);

    ASSERT_EQ(client,expected);
}

标题

#ifndef Client_h
#define Client_h

#include <vector>
#include <string>
#include <sstream>
#include <functional>

enum ClientType {
    Regular,Rewards,};

enum Days {
    Mon = 0,Tues = 1,Wed = 2,Thur = 3,Fri = 4,Sat = 5,Sun = 6,};

class UnkNownDayOfTheWeek
{
public:
    UnkNownDayOfTheWeek(){};
};

class UnkNownClient
{
public:
    UnkNownClient(){};
};


struct Client {
    std::vector<Days> days_;
    ClientType type_;
    
    public: 
        Client(ClientType client_type,std::vector<Days> days) : days_(days),type_(client_type) {};
        Client() {};

        void parse_input(const std::string input);
};

bool operator==(const Client& lhs,const Client& rhs);

#endif

实现:

#include "Client.h"

ClientType parse_client_type(const std::string& client_type_input);
std::vector<Days> parse_client_days(const std::string& client_days_input);

void Client::parse_input(const std::string input) {
    std::string client_type_input = input.substr(0,input.find(":"));
    std::string client_days_input = input.substr(input.find(":"));

    ClientType client_type = parse_client_type(client_type_input);
    std::vector<Days> days = parse_client_days(client_days_input);
    type_ = client_type;
    days_ = days;
}

ClientType parse_client_type(const std::string& client_type_input) {
    if (client_type_input == "Regular") {
        return ClientType::Regular;
    } else if (client_type_input == "Rewards") {
        return ClientType::Rewards;
    } else {
        throw UnkNownClient();
    }
}

std::vector<Days> parse_client_days(const std::string& client_days_input) {
    std::vector<Days> days;
    std::vector<std::string> days_tokens;  
    std::stringstream ss(client_days_input);

    std::string intermediate;
    
    while(getline(ss,intermediate,','))
    {
        days_tokens.push_back(intermediate);
    }

    std::transform(days_tokens.begin(),days_tokens.end(),days.begin(),[](std::string token) { 
        if (token.find("mon") != std::string::npos) {
            return Days::Mon;
        } else if (token.find("tues") != std::string::npos) {
            return Days::Tues;
        } else if (token.find("wed") != std::string::npos) {
            return Days::Tues;
        } else if (token.find("thur") != std::string::npos) {
            return Days::Tues;
        } else if (token.find("fri") != std::string::npos) {
            return Days::Tues;
        } else if (token.find("sat") != std::string::npos) {
            return Days::Tues;
        } else if (token.find("sun") != std::string::npos) {
            return Days::Tues;
        }

        throw UnkNownDayOfTheWeek();
    });

    return days;
}

bool operator==(const Client& lhs,const Client& rhs) {
    return lhs.type_ == rhs.type_ && (lhs.days_.size() == rhs.days_.size() &&
            std::equal(lhs.days_.begin(),lhs.days_.end(),rhs.days_.begin()));
}

终端输出

[----------] 1 test from ClientInputParse
[ RUN      ] ClientInputParse.RegularWeekdays
zsh: segmentation fault  ./test

解决方法

parse_client_days() 中,您对 std::transform() 的使用试图修改 向量 days。当 transform() 尝试写入由 days 迭代器引用的元素时,它会崩溃,因为没有可写入的有效元素。

您需要:

  1. 在调用 days 之前使 day_tokens 的大小与 std::transform() 的大小匹配:
days.resize(days_tokens.size()); // <-- add this
std::transform(days_tokens.begin(),days_tokens.end(),days.begin(),...);
  1. 使用 std::back_inserter() 作为输出迭代器:
std::transform(days_tokens.begin(),std::back_inserter(days),...);