2010-02-09 42 views
7
Collection CollectionFactory::createFromMap(const std::string& name, 
     const DataMap& dm) const 
{ 
    if (!Collection::isNameValid(name)) 
    { 
     const std::string error = "invalid collection name"; 
     throw std::invalid_argument(error); 
    } 
    Collection c(name, dm); 
    dm.initDataCollection(&c, true); 
    return c; 
} 

Bất cứ khi nào câu lệnh ném được thực thi, tôi nhận được lỗi phân đoạn. Đây là nguyên nhân từ đầu ra Valgrind. Tôi không biết chuyện gì đang diễn ra.ném một ngoại lệ gây ra lỗi phân đoạn

==21124== Invalid read of size 1 
==21124== at 0x41D2190: parse_lsda_header(_Unwind_Context*, unsigned char const*, lsda_header_info*) (eh_personality.cc:62) 
==21124== by 0x41D24A9: __gxx_personality_v0 (eh_personality.cc:228) 
==21124== by 0x4200220: _Unwind_RaiseException (unwind.inc:109) 
==21124== by 0x41D2C9C: __cxa_throw (eh_throw.cc:75) 
==21124== by 0x4079BFB: corestore::CollectionFactory::createFromMap(std::string const&, corestore::DataMap const&) const (CollectionFactory.C:43) 
==21124== by 0x8188F86: CollectionFactoryTest::testCreateNewFromMap_InvalidName() (CollectionFactoryTest.C:91) 
==21124== by 0x81895D3: CppUnit::TestCaller<CollectionFactoryTest>::runTest() (TestCaller.h:166) 
==21124== by 0x40D1BB5: CppUnit::TestCaseMethodFunctor::operator()() const (TestCase.cpp:34) 
==21124== by 0x40C18E3: CppUnit::DefaultProtector::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (DefaultProtector.cpp:15) 
==21124== by 0x40CD0FC: CppUnit::ProtectorChain::ProtectFunctor::operator()() const (ProtectorChain.cpp:20) 
==21124== by 0x40CCA65: CppUnit::ProtectorChain::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (ProtectorChain.cpp:77) 
==21124== by 0x40DC6C4: CppUnit::TestResult::protect(CppUnit::Functor const&, CppUnit::Test*, std::string const&) (TestResult.cpp:178) 
==21124== Address 0xc82f is not stack'd, malloc'd or (recently) free'd 

tôi đã có một số lần lặp của bài kiểm tra đơn vị đó là vụ đánh bom, nhưng đây là một hiện rằng cuộc triển lãm các lỗi giống như tất cả những người khác:

void CollectionFactoryTest::testCreateNewFromMap_InvalidName() 
{ 
    const char* MAP_FILE = 
      "smallMapWithThreeSets.xml"; 
    const char* NAME1 = "name/invalidname"; 
    const char* NAME2 = "name/invalidname"; 

    DataMapReader dmr; 
    DataMap dm = dmr.getDataMapFromFile(MAP_FILE); 

    CollectionFactory cf; 
    try 
    { 
     cf.createFromMap(NAME1, dm); 
    } 
    catch (std::exception const& e) 
    { 
     std::cerr << e.what() << std::endl; 
    } 

    /*CPPUNIT_ASSERT_THROW(cf.createFromMap(NAME1, dm), std::invalid_argument); 
    CPPUNIT_ASSERT_THROW(cf.createFromMap(NAME2, dm), std::invalid_argument);*/ 
} 

Theo yêu cầu, nội dung của isNameValid :

bool Collection::isNameValid(const std::string& name) 
{ 
    /* can't be blank */ 
    if(name.length() == 0) 
    { 
     return false; 
    } 
    /* Can't contain '/' */ 
    if(name.find('/') != std::string::npos) 
    { 
     return false; 
    } 
    return true; 
} 

Trả lời

1

Đó có phải là lỗi Valgrind đầu tiên hoặc có lỗi trước đó không?

Đoán của tôi là có những cái trước đó và một trong số đó đang làm hỏng bộ nhớ và gây ra sự cố.

+0

Tất cả các lỗi trước đó liên quan đến giá trị chưa được khởi tạo trong cuộc gọi hệ thống (sigaction, write) hoặc nhảy có điều kiện về giá trị chưa được khởi tạo, vì vậy đây không phải là bộ nhớ bị hỏng. – Dave

+0

Bạn có thể giảm bớt sự cố không? Nếu bạn chỉ chạy testCreateNewFromMap_InvalidName bạn vẫn nhận được segfault? –

+0

Tôi đã tạo một chương trình riêng. Nó chỉ là chính. Tất cả những gì có trong bài kiểm tra đó. Lỗi phân đoạn giống nhau xảy ra. Tôi cũng tạo ra một chương trình riêng biệt mà chỉ ném một ngoại lệ (không sử dụng thư viện của tôi), và nó hoạt động. Ngoài ra, nếu tôi không bắt được, tôi sẽ có lối ra sạch sẽ với một bản in ra khỏi "Bị hủy bỏ". – Dave

1

Bạn liên kết mã như thế nào? Ví dụ, nếu bạn đang tạo một thư viện chia sẻ, có thể bạn cần chỉ định các cờ biên dịch cho mã độc lập, chẳng hạn như -fPIC (gcc/g ++).

+0

Các ngoại lệ được đưa ra trong thư viện được chia sẻ. Thật vậy, khi tôi liên kết tĩnh, lỗi sẽ biến mất. Tuy nhiên, tại nơi làm việc, chúng tôi có hai cấu hình hệ điều hành. Hệ thống 64-bit mới hơn sử dụng 11.1 Intel Compiler thay vì phiên bản 9.1 cũ. Nó cũng sử dụng gcc4 + thay vì 3,3, và nó đang làm việc trên hệ thống mới hơn. Tôi đang chờ đợi để làm việc với intel để xem nếu đây là một vấn đề được biết đến với trình biên dịch 9.1. – Dave

2

Dave, có thiếu mã trên con đường thực hiện của mình, ngăn từ đóng đinh xuống vấn đề:

  • DataMapReader constructor;
  • triển khai DataMapReader :: getDataMapFromFile();
  • Trình tạo bản đồ DataMap;
  • Bộ sưu tậpNgười xây dựng nhà máy;

Tôi khuyên bạn nên thử gỡ bỏ testcase càng nhiều càng tốt trong khi lỗi phân đoạn vẫn có thể tái sản xuất.

Tôi có phỏng đoán sau đây cho các vấn đề:

  • DataMapReader :: getDataMapFromFile() chấp nhận một tham chiếu đến std :: string và sau đó lưu nó hoặc trong bộ nhớ tĩnh hoặc trong DataMapReader dụ hoặc trong DataMap dụ. Điều này dẫn đến hành vi không xác định, vì đối tượng chuỗi std :: được tham chiếu sẽ bị hủy ngay lập tức sau khi thoát khỏi DataMapReader :: getDataMapFromFile(), vì vậy tất cả tham chiếu còn lại sẽ tự động trở thành không hợp lệ.
  • DataMapReader :: getDataMapFromFile() trả về một tham chiếu đến cá thể DataMap được lưu trữ trên ngăn xếp. Ví dụ như vậy sẽ bị hủy ngay sau khi DataMapReader :: getDataMapFromFile() trả về và trước khi hàm tạo bản sao cho dm sẽ được gọi, dẫn đến hành vi không xác định. Trường hợp này là không, bởi vì trình biên dịch thường cảnh báo về việc trả về con trỏ hoặc tham chiếu đến các đối tượng được lưu trữ trên một ngăn xếp.
  • Nếu DataMapReader :: getMapFromFile() trả về DataMap theo giá trị và DataMap không có trình tạo bản sao được xác định rõ ràng và/hoặc toán tử gán bản sao, hoặc nó có triển khai không chính xác cho các nhà xây dựng và/hoặc toán tử đó, xử lý không đúng cách sao chép con trỏ và/hoặc tham chiếu đến các thành viên thuộc sở hữu của DataMap (hoặc các thành viên khác được lưu trữ theo giá trị có cùng một vấn đề đệ quy). Trong trường hợp này, các thành viên được tham chiếu có thể bị hủy trong DataMap destructor được gọi cho cá thể được lưu trữ trên một ngăn xếp trước khi trở về từ DataMapReader :: getMapFromFile(), dẫn đến hành vi không xác định.

Mặc dù điều này là không liên quan đến các lỗi phân khúc được đề cập trong câu hỏi, những vấn đề tiềm năng tương tự có thể áp dụng đối với các mã dưới đây ném ngoại lệ trong CollectionFactory :: createFromMap():

  • Collection constructor không nên lưu trữ các tham chiếu đến các tham số đầu vào (std :: string và DataMap) nếu tuổi thọ của chúng nhỏ hơn thời gian tồn tại của cá thể Collection.
  • DataMap.initDataCollection() không được lưu trữ con trỏ vào cá thể Bộ sưu tập, vì thời gian tồn tại của cá thể Bộ sưu tập được tạo trên ngăn xếp nhỏ hơn thời gian tồn tại của cá thể DataMap. Ví dụ bộ sưu tập sẽ bị hủy trước khi trở về từ CollectionFactory :: createFromMap().
  • Bộ sưu tập phải triển khai đúng cách trình tạo bản sao và/hoặc toán tử gán bản sao, nếu không nó sẽ bị vấn đề nêu trên.
Các vấn đề liên quan