增加地图的分段错误

时间:2018-01-21 00:01:38

标签: c++ pointers dictionary

我正在尝试在程序中跟踪/修复分段错误。当perform()只有一次“protos”迭代时,我的程序工作正常,但没有两次。第二次,我在第一次迭代后得到了一个分段错误。我很确定我在write_blacklist()中处理迭代和删除地图中元素的方式是正确的,但它仍然报告它是错误的。我认为这可能是因为地图是空的,但我做了检查以避免这种情况,但它仍然会引发分段错误。

对于write_blacklist(),所有它应该安全地进行迭代并删除符合条件的地图元素。

(gdb) run
Starting program: /root/BruteBlock/a.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
openssh
vsftpd
115.239.198.235 already in blacklist, skipping...
121.14.7.244 already in blacklist, skipping...
42.7.26.88 already in blacklist, skipping...
143.137.151.22 already in blacklist, skipping...
58.87.67.58 already in blacklist, skipping...
60.173.82.156 already in blacklist, skipping...
[New Thread 0x7ffff2d34700 (LWP 2087)]
[Thread 0x7ffff2d34700 (LWP 2087) exited]
[New Thread 0x7ffff2d34700 (LWP 2088)]
[Thread 0x7ffff2d34700 (LWP 2088) exited]
[New Thread 0x7ffff2d34700 (LWP 2089)]
[Thread 0x7ffff2d34700 (LWP 2089) exited]
Detaching after fork from child process 2090.
115.239.198.235 already in iptables, skipping...
121.14.7.244 already in iptables, skipping...
42.7.26.88 already in iptables, skipping...
143.137.151.22 already in iptables, skipping...
58.87.67.58 already in iptables, skipping...
60.173.82.156 already in iptables, skipping...
[New Thread 0x7ffff2d34700 (LWP 2091)]
[Thread 0x7ffff2d34700 (LWP 2091) exited]

Program received signal SIGSEGV, Segmentation fault.
0x000000000040c1e6 in std::__detail::_Hash_node<std::pair<std::string const, int>, true>::_M_next (this=0x0)
    at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/hashtable_policy.h:285
285       { return static_cast<_Hash_node*>(this->_M_nxt); }
Missing separate debuginfos, use: debuginfo-install cyrus-sasl-lib-2.1.26-21.el7.x86_64 glibc-2.17-196.el7_4.2.x86_64 keyutils-libs-1.5.8-3.el7.x86_64 krb5-libs-1.15.1-8.el7.x86_64 libcom_err-1.42.9-10.el7.x86_64 libcurl-7.29.0-42.el7_4.1.x86_64 libgcc-4.8.5-16.el7_4.1.x86_64 libidn-1.28-4.el7.x86_64 libselinux-2.5-11.el7.x86_64 libssh2-1.4.3-10.el7_2.1.x86_64 libstdc++-4.8.5-16.el7_4.1.x86_64 nspr-4.13.1-1.0.el7_3.x86_64 nss-3.28.4-15.el7_4.x86_64 nss-pem-1.0.3-4.el7.x86_64 nss-softokn-3.28.3-8.el7_4.x86_64 nss-softokn-freebl-3.28.3-8.el7_4.x86_64 nss-sysinit-3.28.4-15.el7_4.x86_64 nss-util-3.28.4-3.el7.x86_64 openldap-2.4.44-5.el7.x86_64 openssl-libs-1.0.2k-8.el7.x86_64 pcre-8.32-17.el7.x86_64 sqlite-3.7.17-8.el7.x86_64 zlib-1.2.7-17.el7.x86_64
(gdb) bt
#0  0x000000000040c1e6 in std::__detail::_Hash_node<std::pair<std::string const, int>, true>::_M_next (this=0x0)
    at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/hashtable_policy.h:285
#1  0x000000000040a829 in std::__detail::_Node_iterator_base<std::pair<std::string const, int>, true>::_M_incr (
    this=0x7fffffffde20) at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/hashtable_policy.h:314
#2  0x0000000000409612 in std::__detail::_Node_iterator<std::pair<std::string const, int>, false, true>::operator++ (
    this=0x7fffffffde20) at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/hashtable_policy.h:369
Python Exception <class 'gdb.error'> There is no member or method named _M_bbegin.: 
#3  0x000000000040597e in BruteBlock::write_blacklist (this=0x7fffffffe130, ips=std::unordered_map with 0 elements, 
    output_file="/etc/blacklist.lst") at BruteBlock.cpp:68
#4  0x0000000000406552 in BruteBlock::perform (this=0x7fffffffe130) at BruteBlock.cpp:188
#5  0x0000000000404e8c in main () at main.cpp:18

main.cpp中:

while (true) {
18: b.perform();
    sleep(b.get_interval());
}

BruteBlock.cpp ::执行():

void BruteBlock::perform() {
    // Hopefully this will become more elegant!
    for (auto i : protos) {
        std::unordered_map<std::string, int> r(retr_fails(i.logfile, i.expr));
        if (r.empty()) {
        } else {
            write_blacklist(r, blacklist_);
188:        block(blacklist_);
        }
    }
}

BruteBlock.cpp :: write_blacklist():

void BruteBlock::write_blacklist(std::unordered_map<std::string, int> &ips, const std::string &output_file) {
    std::ifstream is(output_file.c_str());

    if (!is) throw std::runtime_error("Error opening blacklist");
    if (ips.empty()) return;

    // ignore duplicates
    std::string buf;
    while (std::getline(is, buf)) {
        if (ips.find(buf) != ips.end()) {
            ips.erase(buf);
            std::cout << buf << " already in blacklist, skipping..." << '\n';
        }
    }

    // delete the IPs that don't meet the criteria
    auto a = ips.begin();
    while (a != ips.end()) {
        if (a->second < max_attempts_) {
            a = ips.erase(a);
        } else {
            if (a->second > max_attempts_) {
                if (check_reports(a->first) < max_reports_) {
                    a = ips.erase(a);
                }
            }
68:         ++a;
        }
    }

    // write the remaining IPs to the blacklist
    std::ofstream os(output_file.c_str(), std::ios_base::app);

    if (!os) throw std::invalid_argument("Error opening blacklist file");

    for (auto f : ips) {
        if ((f.second > max_attempts_) && (check_reports(f.first) > max_reports_)) {
            os << f.first << '\n';
            std::cout << f.first << " had " << f.second << " failed attempts and " << check_reports(f.first)
                      << " abuse reports, adding to blacklist...\n";
        }
    }

}

1 个答案:

答案 0 :(得分:0)

在您的上一个循环中,j3在您标有68:的行上方,您有a = ips.erase(a);。如果您要删除地图中的最后一个节点,则a将在擦除后指向ips.end()。当您尝试在第68行增加a时,您会遇到分段错误,因为您无法增加end迭代器的迭代器。

如果您要删除它,解决方法是不增加a