2015-09-06 88 views
1

我一直有一個相當複雜的應用程序的問題,其中valgrind報告與使用函數指針有關的無效讀取大小問題。我試圖將問題減少到可能的最小代碼。基本上,有一個類A定義了一個函數model,它將一些數據作爲參數。類B具有函數指針,該函數指針稍後被設置爲A實例的model函數。函數B->run()然後調用函數指針。使用valgrind函數指針的讀取大小無效

#include <iostream> 
#include <vector> 
#include <functional> 

using namespace std::placeholders; 

class A 
{ 
public: 
    A() {}; 
    ~A(){}; 

    void model(std::vector<double>*); 
}; 

void A::model(std::vector<double>* data) 
{ 
    for (size_t i = 0; i <= (*data).size(); ++i) { 
     std::cout << (*data)[i] << std::endl; 
    } 

    return; 
} 

class B 
{ 
public: 
    B() {}; 
    ~B(){}; 

    void run(); 
    std::function<void(std::vector<double>*)> f_model; 
}; 

void B::run() 
{ 
    std::vector<double> data(10, 1); 
    f_model(&data); 

    return; 
} 

int main(int argc, char** argv) 
{ 
    A* a = new A(); 
    B* b = new B(); 

    b->f_model = std::bind(&A::model, a, _1); 
    b->run(); 

    delete b; 
    delete a; 

    exit(EXIT_SUCCESS); 
} 

下的valgrind運行此我得到的消息

==21841== Invalid read of size 8 
==21841== at 0x400C9B: A::model(std::vector<double, std::allocator<double> >*) (in /home/code/snippets/cpptest/main) 
==21841== by 0x40233D: void std::_Mem_fn<void (A::*)(std::vector<double, std::allocator<double> >*)>::operator()<std::vector<double, std::allocator<double> >*, void>(A*, std::vector<double, std::allocator<double> >*&&) const (in /home/code/snippets/cpptest/main) 
==21841== by 0x4021F0: void std::_Bind<std::_Mem_fn<void (A::*)(std::vector<double, std::allocator<double> >*)> (A*, std::_Placeholder<1>)>::__call<void, std::vector<double, std::allocator<double> >*&&, 0ul, 1ul>(std::tuple<std::vector<double, std::allocator<double> >*&&>&&, std::_Index_tuple<0ul, 1ul>) (in /home/code/snippets/cpptest/main) 
==21841== by 0x401EB0: void std::_Bind<std::_Mem_fn<void (A::*)(std::vector<double, std::allocator<double> >*)> (A*, std::_Placeholder<1>)>::operator()<std::vector<double, std::allocator<double> >*, void>(std::vector<double, std::allocator<double> >*&&) (in /home/code/snippets/cpptest/main) 
==21841== by 0x401B3C: std::_Function_handler<void (std::vector<double, std::allocator<double> >*), std::_Bind<std::_Mem_fn<void (A::*)(std::vector<double, std::allocator<double> >*)> (A*, std::_Placeholder<1>)> >::_M_invoke(std::_Any_data const&, std::vector<double, std::allocator<double> >*) (in /home/code/snippets/cpptest/main) 
==21841== by 0x401152: std::function<void (std::vector<double, std::allocator<double> >*)>::operator()(std::vector<double, std::allocator<double> >*) const (in /home/code/snippets/cpptest/main) 
==21841== by 0x400D3C: B::run() (in /home/code/snippets/cpptest/main) 
==21841== by 0x400E18: main (in /home/code/snippets/cpptest/main) 
==21841== Address 0x5a1c1a0 is 0 bytes after a block of size 80 alloc'd 
==21841== at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==21841== by 0x401FBF: __gnu_cxx::new_allocator<double>::allocate(unsigned long, void const*) (in /home/code/snippets/cpptest/main) 
==21841== by 0x401D8E: std::_Vector_base<double, std::allocator<double> >::_M_allocate(unsigned long) (in /home/code/snippets/cpptest/main) 
==21841== by 0x40199E: std::_Vector_base<double, std::allocator<double> >::_M_create_storage(unsigned long) (in /home/code/snippets/cpptest/main) 
==21841== by 0x401306: std::_Vector_base<double, std::allocator<double> >::_Vector_base(unsigned long, std::allocator<double> const&) (in /home/code/snippets/cpptest/main) 
==21841== by 0x40107D: std::vector<double, std::allocator<double> >::vector(unsigned long, double const&, std::allocator<double> const&) (in /home/code/snippets/cpptest/main) 
==21841== by 0x400D1D: B::run() (in /home/code/snippets/cpptest/main) 
==21841== by 0x400E18: main (in /home/code/snippets/cpptest/main) 
==21841== 
0 
==21841== 
==21841== HEAP SUMMARY: 
==21841==  in use at exit: 0 bytes in 0 blocks 
==21841== total heap usage: 4 allocs, 4 frees, 137 bytes allocated 
==21841== 
==21841== All heap blocks were freed -- no leaks are possible 

我有爲什麼這個無效讀取尺寸出現,但想擺脫它很難。有任何想法嗎?

回答

4

該問題與函數指針無關。該錯誤是在這裏:

for (size_t i = 0; i <= (*data).size(); ++i) { 
    std::cout << (*data)[i] << std::endl; 
} 

您正在閱讀(*data).size()+1元素,即0到(*data).size(),包容性。在你的情況下,這是十個元素std::vector中的11個元素。

<!=更換<=將修復無效讀:

for (size_t i = 0; i != (*data).size(); ++i) { 
    std::cout << (*data)[i] << std::endl; 
} 
+0

你是救世主。令人難以置信的是,我花了兩天的時間來嘗試調試。這是第一次使用函數指針,所以我肯定我必須在那裏做非法的事情。這種情況對我來說經常發生,我第一次使用全新的東西,並總是認爲如果出現問題,它必須處理新事物,並且我忽略了絕對微不足道的錯誤。 – Pankrates

+0

@Pankrates:'for'循環條件下的'<='總是值得仔細看看。 –