【问题标题】:Segmentation fault incrementing a map分段错误增加地图
【发布时间】:2018-01-21 00:01:38
【问题描述】:

我正在尝试跟踪/修复程序中的分段错误。当 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::perform():

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";
        }
    }

}

【问题讨论】:

    标签: c++ pointers dictionary


    【解决方案1】:

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

    如果您要擦除它,解决方案是不增加 a

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-13
      相关资源
      最近更新 更多