LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   c++ vector ::size() nonzero before putting anything in the vector - ?! (https://www.linuxquestions.org/questions/programming-9/c-vector-size-nonzero-before-putting-anything-in-the-vector-696214/)

map250r 01-09-2009 08:34 PM

c++ vector ::size() nonzero before putting anything in the vector - ?!
 
I'm a n00b when it comes to c++, sorry if I did something dumb.

I have a vector

Code:

class QOCC_DECLSPEC QoccApplication : public QApplication
{
(...)       
private:
        std::vector<QPluginLoader*> activePlugins;
};

I put stuff in it depending on argv and argc.

Code:

cout<<"argc "<<argc<<endl;
//activePlugins.clear();
if(argc>1){
  doSomeStuff();
  for(int c = 1;c<argc;c++){
    QString pluginPath = QDir::currentPath() + "/" + argv[c];
    if (QFile::exists(pluginPath))
      activePlugins.push_back(new QPluginLoader(pluginPath));
    else cout<<"Error: Plugin "<<pluginPath.toStdString()<<" not found. Skipping."<<endl;
  }

Later:
Code:

cout<<"plugins: " << activePlugins.size() << endl;
for(uint p=0;p<activePlugins.size();p++){
  if(!activePlugins[p]->load())
    cout<<"Plugin "<<activePlugins[p]->fileName().toStdString()<<" failed to load. Continuing anyway."<<endl;
}

I get a segmentation fault if I run the program with no arguments:
Code:

argc 1
plugins: 1013170

Program received signal SIGSEGV, Segmentation fault.

According to GDB, the problem occurs when I try to load a plugin.
I can fix this by uncommenting the line in green - but I thought that C++ initialized variables automatically.

Am I expected to clear the vector, or not?
I'm using Debian Lenny on AMD64, and GCC 4.2.2.

Thanks

ta0kira 01-09-2009 09:40 PM

No; the problem is somewhere else. Please post your backtrace.
ta0kira

map250r 01-09-2009 10:16 PM

$ gdb ./debug/qOcc
GNU gdb 6.7.1-debian
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu"...
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) r
Starting program: /home/mark/projects/occ-other/qtOccHarness-0.1/debug/qOcc
[Thread debugging using libthread_db enabled]
[New Thread 0x7f83977147c0 (LWP 11639)]
argc 1
plugins: 1013170

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7f83977147c0 (LWP 11639)]
0x000000000041677a in QoccApplication::registerPlugins (this=0x7fff9f86c8c0)
at src/qoccapplication.cpp:77
warning: Source file is more recent than executable.
77 if(!activePlugins[p]->load())
(gdb) bt
#0 0x000000000041677a in QoccApplication::registerPlugins (this=0x7fff9f86c8c0)
at src/qoccapplication.cpp:77
#1 0x00000000004160e0 in main (argc=1, argv=0x7fff9f86c9d8) at src/main.cpp:37
(gdb)


The source file warning is because I uncommented the line that clears the vector.

map250r 01-09-2009 10:37 PM

$ grep -n activePlugins src/qoccapplication.cpp
56: activePlugins.clear();
62: activePlugins.push_back(new QPluginLoader(pList.at(i)));
66: activePlugins.push_back(new QPluginLoader(pluginPath));
75: cout<<"plugins: " << activePlugins.size() << endl;
76: for(uint p=0;p<activePlugins.size();p++){
77: if(!activePlugins[p]->load())
78: cout<<"Plugin "<<activePlugins[p]->fileName().toStdString()<<" failed to load. Continuing anyway."<<endl;


$ grep -n activePlugins inc/qoccapplication.h
56: std::vector<QPluginLoader*> activePlugins;

These are the only lines where activePlugins is used.

ErV 01-09-2009 10:48 PM

There is not enough information to help you.
I think problem might be located at line 62 ("activePlugins.push_back(new QPluginLoader(pList.at(i)));") which isn't provided. Either give full function listings, or check size of activePlugins (print it to stdout/stderr) before and after parsing argc/argv, and especially around mysterious "doSomeStuff()" call.

map250r 01-09-2009 10:58 PM

Quote:

Originally Posted by ErV (Post 3403187)
There is not enough information to help you.
I think problem might be located at line 62 ("activePlugins.push_back(new QPluginLoader(pList.at(i)));") which isn't provided. Either give full function listings, or check size of activePlugins (print it to stdout/stderr) before and after parsing argc/argv, and especially around mysterious "doSomeStuff()" call.

If I run the program without arguments, activePlugins.push_back() shouldn't get called. So size should be 0, correct? Writing "doSomeStuff()" was just my attempt to provide a shorter piece of code, yet show that some things were left out. :)

Code:

void QoccApplication::checkArgs(int &argc, char **argv){
        cout<<"argc "<<argc<<endl;
        //activePlugins.clear();
        if(argc>1){
                if (!strcmp(argv[2],"ask")){
                        //arg is ask - so ask.
                        QStringList pList = QFileDialog::getOpenFileNames((QWidget *)this,"Choose a plugin. Ctrl for multiple.", QDir::currentPath(),"Plugins (*.qop.so)");
                        for(int i = 0;i<pList.size();i++)
                                activePlugins.push_back(new QPluginLoader(pList.at(i)));
                } else for(int c = 1;c<argc;c++){
                        QString pluginPath = QDir::currentPath() + "/" + argv[c];
                        if (QFile::exists(pluginPath))
                                activePlugins.push_back(new QPluginLoader(pluginPath));
                        else        cout<<"Error: Plugin "<<pluginPath.toStdString()<<" not found. Skipping."<<endl;
                }
        }
        //numPlugins=0;
}


map250r 01-09-2009 11:18 PM

OK, something wierd is going on. I made it print the vector size when it prints argc. At that point it is zero. Because argc is 1, everything in the if() gets skipped.
argc 1 plugins: 0
plugins: 1013170

checkArgs() is called when the program loads. The function where the seg fault occurs, registerPlugins(), is called after the gui has initialized.

Code:

int main(int argc, char *argv[])
{

        QoccApplication app( argc, argv );                    //checkArgs is called from here
        QoccHarnessWindow *window = new QoccHarnessWindow();

    window->show();
        app.registerPlugins();
        int retval = app.exec();
        return retval;
}

Code:

QoccApplication::QoccApplication(int &argc, char **argv, int _internal ) :
        QApplication (argc, argv, _internal),
        mySplash (NULL)
{
        checkArgs(argc,argv);
}


map250r 01-09-2009 11:28 PM

OK, shows how much of a newb I am, would it make a difference if I changed
Code:

QoccApplication app( argc, argv );
to something like
Code:

QoccApplication app = new QoccApplication( argc, argv );
What I'm wondering is, will it not stay in memory without the keyword "new"?

I'm modifying an old version of someone else's code (http://qtocc.sourceforge.net/). What are the implications of using the second line in place of the first (if that's not too difficult to explain)?

Thanks
map250r

ErV 01-10-2009 12:33 AM

You should try to debug your program with "gdb"(or another debugger), in step-by-step mode, but you'll have to find/read some tutorials about debugging if you are a newbie. advancedlinuxprogramming.com should explain debugging on linux. If haven't done this before, then you'll need some time to get used to gdb.

Right now I don't see what causes this problem. Is this a complete implementation of "registerPlugins()":?
Code:

cout<<"plugins: " << activePlugins.size() << endl;
for(uint p=0;p<activePlugins.size();p++){
  if(!activePlugins[p]->load())
    cout<<"Plugin "<<activePlugins[p]->fileName().toStdString()<<" failed to load. Continuing anyway."<<endl;
}

Either something accesses activePlugins, or something overwrites part of memory where instance of your application class is located.

Anyway, right now debugging program is your best bet. To my opinion, at least.

And this:
Quote:

QoccApplication app = new QoccApplication( argc, argv );
won't compile because of missing "*".

ErV 01-10-2009 12:43 AM

One serious problem in your code:
Quote:

void QoccApplication::checkArgs(int &argc, char **argv){
....
QStringList pList = QFileDialog::getOpenFileNames((QWidget *)this,"Choose a plugin. Ctrl for multiple.", QDir::currentPath(),"Plugins (*.qop.so)");
....
You must not cast QoccApplication* into QWidget*. Don't do this in Qt. QWidget is not a base classe of QoccApplication. Using this pointer might corrupt internal state of QoccApplication object. When you need to cast pointer to one class into pointer to other, use static_cast or dynamic_cast instead. At least in those cases you'll get segfault immediately, so you'll notice the problem right now, instead of getting hard to catch bugs later (might take a week to find something like this).

Doing something similar in other places might be cause of your problem.

map250r 01-10-2009 08:30 AM

Quote:

Originally Posted by ErV (Post 3403246)
One serious problem in your code:

You must not cast QoccApplication* into QWidget*. Don't do this in Qt. QWidget is not a base classe of QoccApplication. Using this pointer might corrupt internal state of QoccApplication object. When you need to cast pointer to one class into pointer to other, use static_cast or dynamic_cast instead. At least in those cases you'll get segfault immediately, so you'll notice the problem right now, instead of getting hard to catch bugs later (might take a week to find something like this).

Doing something similar in other places might be cause of your problem.

I only do that twice, and neither piece of code is executed before the segfault. The first cast would only happen if argc is not < 1. The second cast never happens because the function (unRegisterPlugins) is not used anywhere.

I have changed to a static cast, but have yet to compile it.

johnsfine 01-10-2009 09:01 AM

I don't see the error in any of the code you have posted. What you have described hints at a couple possibilities:

1) The QoccApplication destructor is being called on that object and then you continue to use it, causing the seg fault.

2) The seg fault occurs on a different QoccApplication object.

I couldn't tell if anyone answered your original question unambiguously: You are not required to clear the vector. The constructor for the vector clears it and that constructor is called automatically by the constructor for the containing class even if you don't do that explicitly.

I don't really trust gdb in C++ code, so I would use some cout's to investigate the two ideas I mentioned above. You could do the same with breakpoints more quickly if you trust gdb.

In each of the following places show the value of the current QoccApplication pointer ("this" if you are in a method of that class):

QoccApplication constructor
QoccApplication destructor
The place you were checking argc
The place right before the seg fault.

Those should tell you whether it is all the same object or not and it should tell you if the construction or destruction is occurring out of correct sequence.

map250r 01-10-2009 09:06 AM

Quote:

Originally Posted by ErV (Post 3403241)
You should try to debug your program with "gdb"(or another debugger), in step-by-step mode, but you'll have to find/read some tutorials about debugging if you are a newbie. advancedlinuxprogramming.com should explain debugging on linux. If haven't done this before, then you'll need some time to get used to gdb.

Right now I don't see what causes this problem. Is this a complete implementation of "registerPlugins()":?
Code:

cout<<"plugins: " << activePlugins.size() << endl;
for(uint p=0;p<activePlugins.size();p++){
  if(!activePlugins[p]->load())
    cout<<"Plugin "<<activePlugins[p]->fileName().toStdString()<<" failed to load. Continuing anyway."<<endl;
}


Yes.
Quote:


Either something accesses activePlugins, or something overwrites part of memory where instance of your application class is located.

Anyway, right now debugging program is your best bet. To my opinion, at least.

And this:

won't compile because of missing "*".
So it would be
QoccApplication *app = ...
but this could not make a difference?

gcc didn't like the static_casts, so I just put 0 in place of (QWidget *)this in both places.

map250r 01-10-2009 09:28 AM

Ugggh. I'm leaning towards stale .o files causing this.

I tried to debug from kDevelop. It complained that it couldn't find the program, even after a clean build (errrm, "Rebuild Project"). I selected "debug" in QMake Manager and did a clean build. Tried to debug again, and now the program works.

I imported this project into kdevelop, and kdevelop had trouble parsing the .pro file IIRC. I get .o files all over the place, and now I'm wondering if it's been using a stale one. I have been using "Rebuild Project" instead of "Build Project", thinking that rebuild would delete any .o files, but now I wonder if it might only delete .o files where it expected to find them, then for some reason link against one elsewhere. How likely is that?

Thanks for the help.

map250r 01-10-2009 09:33 AM

Quote:

Originally Posted by johnsfine (Post 3403556)
I don't see the error in any of the code you have posted. What you have described hints at a couple possibilities:

1) The QoccApplication destructor is being called on that object and then you continue to use it, causing the seg fault.

2) The seg fault occurs on a different QoccApplication object.

I couldn't tell if anyone answered your original question unambiguously: You are not required to clear the vector. The constructor for the vector clears it and that constructor is called automatically by the constructor for the containing class even if you don't do that explicitly.

I don't really trust gdb in C++ code, so I would use some cout's to investigate the two ideas I mentioned above. You could do the same with breakpoints more quickly if you trust gdb.

In each of the following places show the value of the current QoccApplication pointer ("this" if you are in a method of that class):

QoccApplication constructor
QoccApplication destructor
The place you were checking argc
The place right before the seg fault.

Those should tell you whether it is all the same object or not and it should tell you if the construction or destruction is occurring out of correct sequence.

I printed "this" at the last two points, and they were the same. The problem has dissappeared, as I mentioned in another post. Hopefully it stays dissappeared. :-)

I still don't get why the problem went way earlier, when I had the clear() line uncommented...

Thanks
map250r


All times are GMT -5. The time now is 05:53 PM.