LinuxQuestions.org
Visit the LQ Articles and Editorials section
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 01-05-2006, 08:38 PM   #1
urzumph
Member
 
Registered: Jan 2004
Location: Australia
Distribution: Debian
Posts: 168

Rep: Reputation: 30
*** glibc detected *** double free or corruption (C++)


Ok, I'm a relative C++ newb, but I have some idea what this means:
"*** glibc detected *** double free or corruption (!prev): 0x08054810 ***". The strange thing is I don't understand why the particular line I have isolated causes it. The error prints while my program is part way through executing and kills it. By process of excessive printf statements, the following line appears to be the cause :

Code:
void BestOfList::additem(Calander toadd) {
    int score = toadd.score();
    size_t len = Scores.size();
    if(score < 0) {return;}
    printf("Adding to list will continue - score >= 0\n");
    // Calander is failed or just very bad.
    for(unsigned int i = 0; i < len; i++) {
        printf("Checking to see if calander toadd is the same calander %u\n",i);
        if(score == Scores[i]) {
            if(toadd == Calanders[i]) {
                printf("Calander is the same. returning...\n");
                return;
            }
        }
    }

    // We already have calander in the list because the
    // same calander can be created multiple ways
    printf("toadd passed required checks. adding Calander...\n");
    Scores.push_back(score);
    printf("pushed back score\n");
    Calanders.push_back(toadd); // <- Line causing problem
    printf("pushed back calander\n");
    reorder();
    resize();
}
This is part of my BestOfList class:
Code:
class BestOfList {
private:
    vector<int> Scores;
    vector<Calander> Calanders;
    void resize();
    void reorder();
public:
    void additem(Calander toadd);
    int getscore(unsigned int index);
    Calander getcalander(unsigned int index);
    unsigned int length();
    void empty();
};
Snip of stdout/stderr from execution:
Code:
(snip)
Calander is not a failure. Continuing test.
Returning score of 60000
Adding to list will continue - score >= 0
toadd passed required checks. adding Calander...
pushed back score
pushed back calander
Reordering calander...
Resizing Calander...
Appointment at 0,14
Adding appointment 3
(snip)
Adding to list will continue - score >= 0
Checking to see if calander toadd is the same calander 0
toadd passed required checks. adding Calander...
pushed back score
*** glibc detected *** double free or corruption (!prev): 0x08054810 ***
Looking at the dump, it must be some unusual condition - it works at least once before screwing up.

Any Ideas? Even if I knew better what might cause a vector to double-free, I might have a better idea of what is wrong with it...
 
Old 01-05-2006, 09:06 PM   #2
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,376

Rep: Reputation: 147Reputation: 147
Bit of a guess here but I think that you want the toadd argument to be passed in as a reference, otherwise it will just be a copy object and deleted when the method finishes ... maybe ?

graeme.
 
Old 01-05-2006, 10:57 PM   #3
xhi
Senior Member
 
Registered: Mar 2005
Location: USA::Pennsylvania
Distribution: Slackware
Posts: 1,065

Rep: Reputation: 45
Quote:
"*** glibc detected *** double free or corruption (!prev): 0x08054810 ***".
it means that you are calling delete on a ptr that you have already deleted.

i dont see why that would be a problem here with the code you have posted.. ?

graeme .. i dont think that is it.. though the local object is destroyed, the member vector calendars had a copy pushed onto it and should survive..

maybe post a little more code..

i just dont see the problem here..
 
Old 01-06-2006, 02:21 AM   #4
urzumph
Member
 
Registered: Jan 2004
Location: Australia
Distribution: Debian
Posts: 168

Original Poster
Rep: Reputation: 30
That's just it - the majority of my code is very simple - In the code I have written I have not used new, delete, malloc or free.

The only thing I ever really do with pointers is with sscanf, and that section of the program seems to complete without problems.
 
Old 01-06-2006, 06:38 AM   #5
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,376

Rep: Reputation: 147Reputation: 147
The way I understand it is that push_down() doesn't make a copy but a reference. Which was why I feel it would be safer to at least pass toadd as a reference. But as I said that is just a guess.

graeme.
 
Old 01-06-2006, 08:57 AM   #6
xhi
Senior Member
 
Registered: Mar 2005
Location: USA::Pennsylvania
Distribution: Slackware
Posts: 1,065

Rep: Reputation: 45
Quote:
Originally Posted by graemef
The way I understand it is that push_down() doesn't make a copy but a reference. Which was why I feel it would be safer to at least pass toadd as a reference. But as I said that is just a guess.

graeme.

i dont think so.. (see ex at bottom) the way urzumph has created it push_back will store a copy... as for the problem urzumph,
i would consider compiling it if you wanted to upload the code..
i may see somthing,, maybe not.. worth a shot..
but i would like to see where it is coming from also as it does not appear to make sense at this time..


Code:
#include <iostream>
#include <vector>
#include <string>

using namespace std;

class foo{
    public:
        foo(){ lock=1; name=""; }
        void nameFoo(string n) { name=n; }
        void unlock() { lock=0; }
        void print(){ if(!lock) cout << "in a foo: " << name << endl; }
        int lock;
        string name;
};

class foolist{
    public:
        vector<foo> v;
        void add(foo f) { v.push_back(f); }
        void list(){
            for(int i=0; i<v.size(); ++i){
                v[i].print();
            }
        }
};

/* the copy in here will be pushed onto the list, and can be read only from list when it goes out of scope.. */
void bar(foolist& l){
    foo temp;       // this foo is local scope and should DIE
    temp.unlock();  // unlock it so we can be sure it is this one being printed
    temp.nameFoo("dead Foo?");  // name it too just for fun
    l.add(temp);    // push it onto the list from main.
}

int main(){
    foolist l;
    foo f;

    f.unlock();     // unlock it so we can be sure it is this foo
    f.nameFoo("main's Foo");    // name it
    l.add(f);       // add one foo here
    bar(l);         // add another foo that goes out of scope here..
    l.list();       // shows two foos here
    return 0;
}

Last edited by xhi; 01-06-2006 at 08:59 AM.
 
Old 01-06-2006, 09:38 AM   #7
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
xhi that looks correct when I tried it, but is what is happening what you think?
if you add a destructor to the class foo like:
Code:
~foo()
{
	cout <<name <<"  out of scope\n";
}
before the code exits from main the output is
main's Foo out of scope
main's Foo out of scope
main's Foo out of scope
dead Foo? out of scope
dead Foo? out of scope
dead Foo? out of scope
in a foo: main's Foo
in a foo: dead Foo?

whats happening here?

<edit>
Code:
void add(foo f) { v.push_back(f); }
this func is using pass by value and therefore creating its own
copy.
</edit>

Last edited by dmail; 01-06-2006 at 09:48 AM.
 
Old 01-06-2006, 09:43 AM   #8
xhi
Senior Member
 
Registered: Mar 2005
Location: USA::Pennsylvania
Distribution: Slackware
Posts: 1,065

Rep: Reputation: 45
>> whats happening here?

wow.. im not completely sure.. i tested that about a dozen different ways. and put the lock and a name in there to be sure..

i am definately going to research this.. unless you can give me a summary dmail..

would be much appreciated..
 
Old 01-06-2006, 09:51 AM   #9
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
after noticing this i wonder if the same thing is the reason for urzumph's question,as its being passed by value aswell?
 
Old 01-06-2006, 09:53 AM   #10
xhi
Senior Member
 
Registered: Mar 2005
Location: USA::Pennsylvania
Distribution: Slackware
Posts: 1,065

Rep: Reputation: 45
>> after noticing this i wonder if the same thing is the reason for urzumph's question,as its being passed by value aswell?

yes very true..
me and my example may very well stand corrected..

good catch..

it appears there is a little more going on underneath a simple little program than i though.. scary...
 
Old 01-06-2006, 10:20 AM   #11
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,376

Rep: Reputation: 147Reputation: 147
I changed the code to pass the f into the method add() by reference. The destructor showed a total of five object being destroyed.

I then changed it to pointers and it was back to the expected three

Code:
#include <iostream>
#include <vector>
#include <string>

using namespace std;

class foo{
    public:
        foo(){ lock=1; name=""; }
        ~foo(){cout <<name <<"  out of scope\n";}
        void nameFoo(string n) { name=n; }
        void unlock() { lock=0; }
        void print(){ if(!lock) cout << "in a foo: " << name << endl; }
        int lock;
        string name;
};

class foolist{
    public:
        vector<foo*> v;
        void add(foo* f) { f->nameFoo("in foolist"),v.push_back(f); }
        void list(){
            for(int i=0; i<v.size(); ++i){
                v[i]->print();
            }
        }
};

/* the copy in here will be pushed onto the list, and can be read only from list when it goes out of scope.. */
void bar(foolist& l){
    foo temp;       // this foo is local scope and should DIE
    temp.unlock();  // unlock it so we can be sure it is this one being printed
    temp.nameFoo("dead Foo?");  // name it too just for fun
    l.add(&temp);    // push it onto the list from main.
    temp.nameFoo("dead Foo?");  // name it too just for fun
}

int main(){
    foolist l;
    foo f;

    f.unlock();     // unlock it so we can be sure it is this foo
    f.nameFoo("main's Foo");    // name it
    l.add(&f);       // add one foo here
    f.nameFoo("main's Foo");    // name it
    bar(l);         // add another foo that goes out of scope here..
    l.list();       // shows two foos here
    return 0;
}
Output:
Code:
dead Foo?  out of scope
in a foo: main's Foo
in a foo: dead Foo?
main's Foo  out of scope
Press Enter to continue!

graeme.
 
Old 01-06-2006, 10:26 AM   #12
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,376

Rep: Reputation: 147Reputation: 147
Err sorry can't count, that look like two?
 
Old 01-06-2006, 10:53 AM   #13
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,376

Rep: Reputation: 147Reputation: 147
Okay I created a copy constructor and wrapped the push_back with diagnostics

It was creating a copy for the object when it is passed into the add() method and then creating a copy when it is pushed onto the vector

When the second element is pushed onto the vector the original element is copied the vector is then populated with new copies and the original copy destroyed.

I added a third element and got three copies and two destroys

Thinking I saw a pattern I added the original foo object f. This resulted in a single copy no destroys.

Added a fifth object and it was back to the original pattern of 5 copies and four destroys and so I think this is how the memory is allocated for the vector.

You create a vector it will have sufficient memory for one element.
Add a second element then it will need to allocate more memory.

Now here is the speculation... It wants the memory to be contiguous and so it recreates itself and copies the data across. Pointers to objects shouldn't be a problem but references cause the copy constructor to kick in.

graeme.
 
Old 01-06-2006, 11:54 AM   #14
xhi
Senior Member
 
Registered: Mar 2005
Location: USA::Pennsylvania
Distribution: Slackware
Posts: 1,065

Rep: Reputation: 45
great work graemef..
i knew this but had locked away in my mind (behind some bong resin probably)..

this is from thinking in c++ vol2
Code:
Vector
Cost of overflowing allocated storage
A vector starts by grabbing a block of storage, as if itís taking a guess at how many objects
you plan to put in it. As long as you donít try to put in more objects than can be held in the
initial block of storage, everything is very rapid and efficient (note that if you do know how
many objects to expect, you can pre-allocate storage using reserve( )). But eventually you
will put in one too many objects and, unbeknownst to you, the vector responds by:
1. Allocating a new, bigger piece of storage
2. Copying all the objects from the old storage to the new (using the copy-constructor)
3. Destroying all the old objects (the destructor is called for each one)
4. Releasing the old memory
For complex objects, this copy-construction and destruction can end up being very expensive
if you overfill your vector a lot. To see what happens when youíre filling a vector, here is a
class that prints out information about its creations, destructions, assignments and copyconstructions:
so thats what was causing our unexpected results.. ??

use vector::reserve(int) to init the vectors storage.. not number of elements.. but contiguous storage available..
add this constructor to my code..
Code:
foolist(){ v.reserve(10); }
 
Old 01-06-2006, 11:58 AM   #15
xhi
Senior Member
 
Registered: Mar 2005
Location: USA::Pennsylvania
Distribution: Slackware
Posts: 1,065

Rep: Reputation: 45
oh yeh... here is the current output.. maybe i have just been looking too hard.. but i dont see where the top two are coming from?
Code:
main's Foo out of scope              <--- ???
dead Foo? out of scope               <--- ???
dead Foo? out of scope
in a foo: main's Foo
in a foo: dead Foo?
main's Foo out of scope
in foolist::~foolist()
main's Foo out of scope
dead Foo? out of scope
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
*** glibc detected *** malloc() / free()/ double RohanShrivastav Programming 12 10-01-2012 10:08 AM
FC3 glibc detected *** double free or corruption: josedragone Fedora 5 09-17-2009 10:16 PM
*** glibc detected *** double free or corruption (!prev): 0x082c1120 *** eXor Slackware 6 04-11-2008 08:47 AM
glibc detected ; memory corruption pingu Linux - Software 3 10-12-2005 01:29 AM
Open Office user install error: *** glibc detected *** double free or corruption: 0xb r_jensen11 Linux - General 6 01-16-2005 06:08 AM


All times are GMT -5. The time now is 06:58 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration