Thread: crashing

  1. #1
    Registered User
    Join Date
    Jul 2009
    Location
    Croatia
    Posts
    272

    crashing

    Hm, the code seems to crash in merge_stats function (i marked it red) and i have no idea why? When i enter only one name and value, it's ok, but when i enter more then one name and value it crashes...

    Code:
    #include <iostream>
    #include <map>
    #include <numeric>
    #include <set>
    #include <string>
    
    using namespace std;
    
    typedef multiset<double> SubData;
    typedef map<string, SubData> Data;
    
    void collect_data(Data &stats)
    {
         string name;
         while(cin >> name) {
             double val;
             cin >> val;
             stats[name].insert(val);
         }
    }
    
    void print_setstats(SubData const &stats)
    {
         size_t count = 0;
         double sum = 0.0, median;
         
         for(SubData::const_iterator p = stats.begin(); p != stats.end(); p++, count++) {
             if(count == (stats.size() - 1) / 2) {
                 median = *p;
                 if(stats.size() % 2 == 0) {
                     SubData::const_iterator q = p;
                     q++;
                     median = (median + (*q))/2.0;
                 }
             }
             sum += *p;
         }
         cout << "sum: " << sum
              << ", mean: " << sum/ (double) count
              << ", median: " << median << endl;
    }
    
    void merge_stats(SubData &dst, SubData &src)
    {
         SubData::iterator hint = dst.begin();
         
         for(SubData::iterator p = src.begin(); p != src.end(); p++) {
                 hint = dst.insert(hint, *p);
                 src.erase(p);
         }
    }
    
    void print_stats(Data &stats)
    {
         SubData global_set;
         
         for(Data::iterator p = stats.begin(); p != stats.end(); p++) {
             cout << (*p).first << ": ";
             print_setstats((*p).second);
             merge_stats(global_set, (*p).second);
         }
         cout << "Global stats: ";
         print_setstats(global_set);
    }
    
    int main()
    {     
          Data stats;
          collect_data(stats);
          print_stats(stats);
          return 0;
    }

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    I don't know enough about multisets to say, but this looks dangerous:
    Code:
         for(SubData::iterator p = src.begin(); p != src.end(); p++) {
                 hint = dst.insert(hint, *p);
                 src.erase(p);
         }
    Are you sure that erase()'ing at the iterator doesn't invalidate it?
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Registered User
    Join Date
    Jul 2009
    Location
    Croatia
    Posts
    272
    True, i figured that just out. Thanks. I'll look it up...

  4. #4
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Typical correct way of erasing from a container whilst iterating over it:
    Code:
    for (it = c.begin(); it != c.end();)
    {
        if (condition(*it))
            it = c.erase(it);
        else
            ++it;
    }
    works with all container types, though in a vector it is O(n^2).
    Hence for a vector the erase/remove_if idiom is often used instead.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by iMalc
    works with all container types
    No, it only works with all standard sequence container types. Rather:
    Code:
    it = c.erase(it);
    should be:
    Code:
    c.erase(it++);
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Strange windows STL crashing problem
    By kdmiller in forum C++ Programming
    Replies: 5
    Last Post: 06-23-2010, 02:25 PM
  2. Programming crashing error
    By Neotriz in forum C Programming
    Replies: 1
    Last Post: 11-26-2009, 07:31 AM
  3. Program crashing at fgets() - any ideas why?
    By avi2886 in forum C Programming
    Replies: 4
    Last Post: 03-06-2009, 09:24 PM
  4. std::map::find() crashing
    By noobcpp in forum C++ Programming
    Replies: 13
    Last Post: 12-28-2008, 11:12 PM
  5. Compiler Crashing... WHY?
    By kippwinger in forum C++ Programming
    Replies: 6
    Last Post: 07-03-2003, 12:10 AM