2010-10-20 31 views
5

Có ai biết nếu nó kosher để vượt qua một tăng :: unordered_set như tham số đầu tiên để tăng :: chia? Dưới libboost1.42-dev, điều này dường như gây ra vấn đề. Dưới đây là một chương trình ví dụ nhỏ mà gây ra vấn đề, gọi nó là test-split.cc:Vượt qua một tăng :: unordered_set như là bản đồ kết quả để tăng :: tách

#include <boost/algorithm/string/classification.hpp> 
#include <boost/algorithm/string/split.hpp> 
#include <boost/unordered_set.hpp> 
#include <string> 

int main(int argc, char **argv) { 
    boost::unordered_set<std::string> tags_set; 
    boost::split(tags_set, "a^b^c^", 
       boost::is_any_of(std::string(1, '^'))); 
    return 0; 
} 

Sau đó, nếu tôi chạy các lệnh sau:

g++ -o test-split test-split.cc; valgrind ./test-split 

tôi nhận được một loạt các khiếu nại trong valgrind như một trong đó sau (tôi cũng thỉnh thoảng thấy coredumps mà không valgrind, mặc dù nó có vẻ khác nhau dựa trên thời gian):

==16843== Invalid read of size 8 
==16843== at 0x4ED07D3: std::string::end() const (in /usr/lib/libstdc++.so.6.0.13) 
==16843== by 0x401EE2: unsigned long boost::hash_value<char, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /tmp/test-split) 
... 
==16843== by 0x402248: boost::unordered_set<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::string> >& boost::algorithm::split<boost::unordered_set<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::string> >, char const [26], boost::algorithm::detail::is_any_ofF<char> >(boost::unordered_set<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::string> >&, char const (&) [26], boost::algorithm::detail::is_any_ofF<char>, boost::algorithm::token_compress_mode_type) (in /tmp/test-split) 
==16843== by 0x40192A: main (in /tmp/test-split) 
==16843== Address 0x5936610 is 0 bytes inside a block of size 32 free'd 
==16843== at 0x4C23E0F: operator delete(void*) (vg_replace_malloc.c:387) 
==16843== by 0x4ED1EE8: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/libstdc++.so.6.0.13) 
==16843== by 0x404A8B: void boost::unordered_detail::hash_unique_table<boost::unordered_detail::set<boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::string> > >::insert_range_impl<boost::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::string, char const*>, boost::algorithm::split_iterator<char const*>, boost::use_default, boost::use_default> >(std::string const&, boost::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::string, char const*>, boost::algorithm::split_iterator<char const*>, boost::use_default, boost::use_default>, boost::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::string, char const*>, boost::algorithm::split_iterator<char const*>, boost::use_default, boost::use_default>) (in /tmp/test-split) 
... 
==16843== by 0x402248: boost::unordered_set<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::string> >& boost::algorithm::split<boost::unordered_set<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::string> >, char const [26], boost::algorithm::detail::is_any_ofF<char> >(boost::unordered_set<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::string> >&, char const (&) [26], boost::algorithm::detail::is_any_ofF<char>, boost::algorithm::token_compress_mode_type) (in /tmp/test-split) 
==16843== by 0x40192A: main (in /tmp/test-split) 

Đây là một hộp Bóp Debian; ở đây có liên quan thông tin hệ thống của tôi:

$ g++ --version 
g++ (Debian 4.4.5-2) 4.4.5 
Copyright (C) 2010 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

$ dpkg -l | grep boost 
ii libboost-iostreams1.42.0   1.42.0-4      Boost.Iostreams Library 
ii libboost1.42-dev     1.42.0-4      Boost C++ Libraries development files 
$ uname -a 
Linux gcc44-buildvm 2.6.32-5-amd64 #1 SMP Fri Sep 17 21:50:19 UTC 2010 x86_64 GNU/Linux 

Tuy nhiên, mã dường như làm việc tốt nếu tôi hạ cấp libboost1.42-dev để libboost1.40-dev. Vì vậy, đây là một lỗi trong tăng 1,42, hoặc tôi lạm dụng tăng :: chia bằng cách đi qua trong một container mà không thể xử lý các trình tự? Cảm ơn!

+0

FWIW, tôi chỉ có thể tạo lại các lỗi valgrind này với 'boost :: unordered_set', trong khi đó, lệnh' std :: unordered_set' valgrinds của GCC lặng lẽ. – Cubbi

+11

Có lẽ các ví dụ sau đây có thể đáng xem xét vì chúng đơn giản và hiệu quả hơn nhiều: http: //www.codeproject.com/KB/recipes/Tokenizer.aspx Cụ thể là phần "Một số ví dụ đơn giản". –

Trả lời

2

Điều này đã được xác nhận trên danh sách gửi thư nâng cao của người dùng là một lỗi trong triển khai tăng cường :: unordered_set.Có một bản vá có sẵn trên danh sách gửi thư và bản sửa lỗi sẽ sớm được kiểm tra, hy vọng trong thời gian tăng 1,45.

Boost-users: patch

Boost-users: confirmation

Cảm ơn tất cả mọi người nhìn vào điều này!

0

Rõ ràng, câu trả lời là không .

Sử dụng mã sau, tôi nhận được cảnh báo thời gian biên dịch và xác nhận thời gian chạy (Visual C++ v10) trên unordered_set trong khi vector hoạt động tốt (ngoài chuỗi trống trong phần tử cuối cùng, do dấu '^').

boost::unordered_set<std::string> tags_set; 
vector<string> SplitVec; // #2: Search for tokens 
boost::split(SplitVec, "a^b^c^", boost::is_any_of("^")); 
boost::split(tags_set, "a^b^c^", boost::is_any_of("^")); 

Tương thích Iterator giữa nguồn (string) và vùng chứa đích là vấn đề. Tôi sẽ đăng lỗi cảnh báo, nhưng đó là một trong những cảnh báo mẫu "Chiến tranh và Hòa bình".

EDIT:

Điều này giống như lỗi trong Boost unordered_set? Khi tôi sử dụng thông tin sau, nó hoạt động như bạn mong đợi:

std::unordered_set<std::string> tags_set_std; 
boost::split(tags_set_std, string("a^b^c^"), boost::is_any_of(string("^"))); 
+0

Cảm ơn Steve. Bạn đang sử dụng phiên bản tăng cường nào? –

+0

@Jeremy - 1.44.0 –

+0

@Jeremy - xem EDIT –

0

Tôi nghĩ câu trả lời phải là có.

Đọc tiêu đề (split.hppiter_find.hpp) split mất một SequenceSequenceT& Result như là đối số đầu tiên của nó, mà nó đi để iter_split mà phạm vi-xây dựng nó từ hai boost::transform_iterator s:

SequenceSequenceT Tmp(itBegin, itEnd); 
Result.swap(Tmp); 
return Result; 

Vì vậy, tất cả những gì cần thuộc loại này là nó có một hàm tạo lấy một cặp các trình vòng lặp mà dereference là std::string (hoặc về mặt kỹ thuật, đến BOOST_STRING_TYPENAME). Và có thành viên .swap() .. và có loại SequenceSequenceT::iterator có loại là std::string.

bằng chứng:

#include <boost/algorithm/string/classification.hpp> 
#include <boost/algorithm/string/split.hpp> 
#include <string> 
#include <iterator> 
#include <algorithm> 
#include <iostream> 
struct X 
{ 
    typedef std::iterator<std::forward_iterator_tag, 
      std::string, ptrdiff_t, std::string*, std::string&> 
      iterator; 
    X() {} 
    template<typename Iter> X(Iter i1, Iter i2) 
    { 
     std::cout << "Constructed X: "; 
     copy(i1, i2, std::ostream_iterator<std::string>(std::cout, " ")); 
     std::cout << "\n"; 
    } 
    void swap(X&) {} 
}; 
int main() 
{ 
    X x; 
    boost::split(x, "a^b^c^", boost::is_any_of(std::string(1, '^'))); 
} 

Tôi nghĩ rằng unordered_set<std::string> phải thoả mãn các yêu cầu này là tốt.

+0

Cảm ơn @Cubbi. Vì vậy, kết luận của bạn là đây là một lỗi ở đâu đó trong Boost 1,42, và rằng các cảnh báo trình biên dịch được nhìn thấy bởi @Steve trên VisualC++/boost 1.44 là sai lầm? –

+0

@Jeremy Stribling: Đó là những gì tôi mong đợi, nhìn thấy thử nghiệm của tôi và gcc unordered_set làm việc như thế nào của boost không, nhưng họ có thể có một lý do chính đáng. Tôi sẽ đợi thêm câu trả lời ở đây và kiểm tra thêm trước khi gọi nó là một lỗi. – Cubbi

+0

@Jeremy - xem chỉnh sửa, tôi đã làm việc này với 'std :: unordered_set' thay vì' boost :: unordered_set' –

Các vấn đề liên quan