Skip to main content
GameDev.net gamedev.net
🔒 Locked

[GCC 4.2.3] std::sort bug

Started by Basiror Aug 7, 2009 at 6:57 PM 9 replies 3.3k views
Original Post
Basiror
Basiror
Hello, I think I spotted a bug in std::sort or my GCC binary On Ubuntu Hardy 8.04: Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.2 --program-suffix=-4.2 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.2.3 (Ubuntu 4.2.3-2ubuntu7) Running the following code gives me a wrong output: Compiled with g++ -o huffman main.cpp main.cpp

  1 #include "huffman.h"
  2                                                                                                                   
  3 int main( int argc, char** argv)
  4 {                    
  5     std::vector< unsigned int> symbols; 
  6     symbols.push_back(1);                
  7     symbols.push_back(2);                
  8     symbols.push_back(3);                
  9     symbols.push_back(4);                
 10     symbols.push_back(2);
 11     symbols.push_back(2);
 12     symbols.push_back(1);
 13                          
 14     const Node* root = BuildHuffmanTree(symbols);      
 15     root->Print();                                              
 16     return 0;                                                                                                     
 17 };  



huffman.h

  1 #ifndef HUFFMAN_H
  2 #define HUFFMAN_H
  3 #include <deque>
  4 #include <vector>
  5 #include <algorithm>
  6 #include <iostream>
  7 #include <iterator>
  8 
  9 typedef unsigned int uint;
 10 typedef std::vector< uint > SymbolVector;
 11 
 12 class Node
 13 {
 14 public:
 15     typedef std::deque< Node* > Queue;
 16 public:
 17     const uint weight;
 18     SymbolVector symbol;
 19     const Node* left;
 20     const Node* right;
 21 public:
 22     Node(const uint _weight, const uint _symbol) : weight(_weight),symbol(1,_symbol),left(0),right(0) {};
 23     Node(const Node* _left, const Node* _right)
 24         :
 25             weight(_left->weight + _right->weight),
 26             left(_left),right(_right)
 27     {
 28         symbol.insert(symbol.end(),left->symbol.begin(),left->symbol.end());
 29         symbol.insert(symbol.end(),right->symbol.begin(),right->symbol.end());
 30     };
 31     void Print() const
 32     {
 33         std::ostream_iterator<uint> ot(std::cout,", ");
 34         std::copy(symbol.begin(),symbol.end(),ot);
 35         std::cout<<"weight: "<<weight<<std::endl;
 36         if(left) left->Print();
 37         if(right) right->Print();
 38     };
 39 };
 40 
 41 inline const bool queue_pred(const Node* a, const Node* b)
 42 {
 43     return a->weight < b->weight;
 44 };
 45 
 46 inline const Node* BuildHuffmanTree(const SymbolVector& csymbols)
 47 {
 48     SymbolVector uniquesymbols(csymbols);
 49     std::sort(uniquesymbols.begin(),uniquesymbols.end());
 50 
 51     std::ostream_iterator<uint> ot(std::cout,", ");
 52     std::copy(uniquesymbols.begin(),uniquesymbols.end(),ot);
 53     {
 54         SymbolVector::iterator i = std::unique(uniquesymbols.begin(),uniquesymbols.end());
 55         uniquesymbols.resize(uniquesymbols.end()-i);
 56     }
 57     std::cout<<uniquesymbols.size()<<std::endl;
 58     Node::Queue queue;
 59 
 60     for(SymbolVector::iterator i=uniquesymbols.begin();i!=uniquesymbols.end();++i)
 61     {
 62         const uint weight = std::count(csymbols.begin(),csymbols.end(),*i);
 63         queue.push_back( new Node(weight,*i) );
 64     }
 65 
 66     while(queue.size() > 1)
 67     {
 68         std::sort(queue.begin(),queue.end(),queue_pred);
 69         const Node* left = queue.front();   queue.pop_front();
 70         const Node* right = queue.front();  queue.pop_front();
 71         queue.push_back( new Node(left,right) );
 72     }
 73 
 74     const Node* result = queue.front();
 75     return result;
 76 };
 77 
 78 
 79 #endif




The output is: ./huffman 1, 1, 2, 2, 2, 3, 4, 3 2, 3, 1, weight: 6 2, weight: 3 3, 1, weight: 3 3, weight: 1 1, weight: 2 the first line should be: 1, 1, 2, 2, 2, 3, 3, 4, So either I did something wrong in my code or I just discovered a bug. Could some of you try to compile this source snipped and compare the results? Please also provide information about your compiler and OS. thx in advance.
http://www.8ung.at/basiror/theironcross.html
Oxyd
Oxyd
Quote:
Original post by Basiror
Could some of you try to compile this source snipped and compare the results?
Please also provide information about your compiler and OS.


Can you please remove the leading line numbers? It won't compile with them and I don't want to remove them manually.
magic_man
magic_man
I can not see for sure from a quick glance but why are you expecting two instances of three when you only insert one?
Does the final "3" come from the following line?
std::cout<<uniquesymbols.size()<<std::endl;
"You insulted me!" I did not say that in the private message Tom Sloper!
dmatter
dmatter
Quote:
Original post by magic_man
Does the final "3" come from the following line?
Yep, it looks that way. The last bit of output leaves a trailing comma which makes the 3 look like part of the sequence.
Sc4Freak
Sc4Freak
Rule of thumb: if you're using a modern compiler and you think you've found a compiler bug, you haven't.
MaulingMonkey
MaulingMonkey
Quote:
Original post by Sc4Freak
Rule of thumb: if you're using a modern compiler and you think you've found a compiler bug, you haven't.


For the advanced: If you're using a modern compiler and you think you've found a compiler bug, you haven't, until you've categorically located the erroneous lines of code, created a fix, provided a workaround, reported it upstream to your compiler vendor, and have received independent confirmation from that compiler vendor, and seen the bug fixed and/or given a target release to be fixed by. Which looks something like this [lol]. And even if you did manage to get all those steps in, it was probably a dream, and you probably still have a bug in your own code that triggered their bug ;-)
Basiror
Basiror
Oh yeah, it was my fault, but it was late at night so :)

thx for your help anyways

Maybe some moderator could delete this thread?

http://www.8ung.at/basiror/theironcross.html
SiCrane
SiCrane
Quote:
Original post by MaulingMonkey
and seen the bug fixed and/or given a target release to be fixed by.


I've actually submitted two bugs for MSVC that got "Will not fix" as the response.
rip-off
rip-off
This is why you create a *minimal* program. Had you removed the unnecessary output you probably would have spotted this yourself.
Zahlman
Zahlman
Of course, there should be 4 unique symbols reported rather than 3.

But the reason you get a wrong result there is that 'uniquesymbols.resize(uniquesymbols.end()-i)' should be 'uniquesymbols.resize(i - uniquesymbols.begin())'. Although the idiomatic way to do it would be 'uniquesymbols.erase(i, uniquesymbols.end()). :)
iMalc
iMalc
Quote:
Original post by Basiror
Maybe some moderator could delete this thread?
No, that's not what happens on forums. Threads like this aren't just for your benefit. Most likely others will at some point have a similar problem and will see the solution here, or even if they don't have a problem, they might learn how to do something properly from reading someone else's replies.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.