C.bad_alloc异常对future.get

时间:2019-01-29 16:36:46

标签: c++ c++11 debugging memory gdb

我的C ++程序因bad_alloc异常退出。我正在尝试查找原因,但是不太了解如何调试此类异常。

到目前为止,我已在调试模式下编译了程序,使用gdb运行该程序并设置了一个断点,然后引发异常(b 'std::bad_alloc::bad_alloc()')。

引发异常后,我检查了堆栈(bt),该堆栈显示以下内容:

(gdb) bt
#0  0x00007ffff752f1f7 in raise () from /lib64/libc.so.6
#1  0x00007ffff75308e8 in abort () from /lib64/libc.so.6
#2  0x00007ffff7f0a7fd in __gnu_cxx::__verbose_terminate_handler () at ../../../../libstdc++-v3/libsupc++/vterminate.cc:95
#3  0x00007ffff7f08876 in __cxxabiv1::__terminate (handler=<optimized out>) at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:47
#4  0x00007ffff7f088c1 in std::terminate () at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:57
#5  0x00007ffff7f0886a in std::rethrow_exception (ep=...) at ../../../../libstdc++-v3/libsupc++/eh_ptr.cc:259
#6  0x0000000000419001 in std::__basic_future<void>::_M_get_result (this=0x55b9a0)
    at /soft/EB_repo/devel/programs/foss/2016b/GCCcore/5.4.0/include/c++/5.4.0/future:683
#7  0x0000000000416da6 in std::future<void>::get (this=0x55b9a0) at /soft/EB_repo/devel/programs/foss/2016b/GCCcore/5.4.0/include/c++/5.4.0/future:846
#8  0x00000000004d152f in cluster_reads (reads=..., kmer_size=14, t_s=0.10000000000000001, t_v=500, bv_threshold=0.40000000000000002, 
    min_bv_threshold=0.20000000000000001, bv_falloff=0.050000000000000003, min_reads_cluster=0, n_threads=8) at cluster.cpp:81
#9  0x000000000040910b in main (argc=8, argv=0x7fffffffc028) at main.cpp:106

如您在#7中所见,获取std :: future时会抛出异常?这是来自cluster_reads(#8)的崩溃代码段(我用箭头标记了第81行)。

    std::vector<std::vector<kmer_t>> kmers(reads.size());
    std::vector<std::vector<kmer_t>> rev_kmers(reads.size());

    std::vector<kmer_bv_t> bv_kmers(reads.size());
    std::vector<kmer_bv_t> rev_bv_kmers(reads.size());

    std::vector<std::future<void>> tasks;
    for (int t = 0; t < n_threads; ++t) {
        tasks.emplace_back(std::async(std::launch::async, [t, &reads, n_threads, kmer_size, &kmers, &rev_kmers, &bv_kmers, &rev_bv_kmers] {
            for (int i = t; i < reads.size(); i+=n_threads) {
                read_kmers_t k1 = extract_kmers_from_read(reads[i].seq, kmer_size);

                kmers[i] = k1.list_forward;
                rev_kmers[i] = k1.list_reverse;
                bv_kmers[i] = k1.bv_forward;
                rev_bv_kmers[i] = k1.bv_reverse;
            }
        }));
    }

    for (auto &&task : tasks) {
        task.get(); <------------------- line 81
    }

如何进一步调试此问题?我是gdb的新手。关于可能导致bad_alloc异常的原因有什么想法吗?

1 个答案:

答案 0 :(得分:1)

似乎在一个线程中抛出了std::bad_alloc,后来又被task.get()抛弃了(您错误地认为这是异常的来源)。这是来自future::get() cppreference

的引用
  

例外   如果异常存储在将来引用的共享状态中(例如,通过调用std::promise::set_exception()),则该异常将被抛出。

这可能是由于在以下位置分配了std::vector<kmer_t>

read_kmers_t k1 = extract_kmers_from_read(reads[i].seq, kmer_size);

以及以后的版本:

kmers[i] = k1.list_forward;

从变量的名称中,我假设您正在读取基因组数据库,如果您不小心的话,它可能很大并且会耗尽您的内存。

要捕获引发异常的确切时刻,您应该告诉gdb:

 (gdb) catch throw

将在引发原始异常的地方停止执行。