0

First off, I'm new to c++. If there's a better way to do this then a structure, please mention it.

So what I'm trying to do is create a structure to store pointers to some custom objects. The reason for this is instead of having to pass many pointers of parameters, I can declare this structure and pass the structure to the function that needs this group of objects.

The reason for all the objects is I am doing repative interactions with web services. I have made a class to simplify the interactions with the web services and do not wish to destroy and recreate them every time I need them.

Note: This is being done in Qt 5

This is in the header:

struct MyStruct
{
    MyClass* Class1;
    MyClass* Class2;
    MyClass* Class3;
    MyClass* Class4;
};

Now this is a snip of how I'm trying to fill in the structure:

//Stucture of commonly used objects, for all to access
MyStruct* theStruct;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    //Build object
    MyClass* firstClass = new MyClass(/*params for object*/);
    theStruct->Class1 = firstClass;

    ui->setupUi(this);
    connect(firstclass, SIGNAL(dataReady()),this,SLOT(updateWebStats(MyStruct)));
}

And now the error I am getting:

App output:

Starting MyExe.exe Error - RtlWerpReportException failed with status code :-1073741823. Will try to

launch the process directly:

The program has unexpectedly finished. MyExe.exe crashed

When I debug I get a popup

The inferior stopped because it received a signal from the Operating System.

Signal name : SIGSEGV
Signal meaning : Segmentation fault

At this time the debugger is at this line, in the mainwindow constructor:

theStruct->Class1 = firstClass;
Alois Mahdal
  • 10,763
  • 7
  • 51
  • 69
Dave851
  • 5
  • 8

3 Answers3

2

You are trying to access an unassigned pointer which results in a segmentation fault.

Try initialize it:

MyStruct* theStruct = new MyStruct();
Johan Karlsson
  • 6,419
  • 1
  • 19
  • 28
  • Yea this was the problem, thanks. New to c++ and didn't realize structures are constructed like classes, thought they only needed a type. I would vote you up but it won't let me – Dave851 Oct 18 '14 at 01:40
  • Neither structures nor classes need to be initialized with `new`, and you should not do so unless you have a compelling reason for it. See my answer below. – Vector Oct 18 '14 at 10:23
2

I don't agree with the idea of using globals to make life easier. Are global variables bad?

But here is your error.

theStruct, must also be initialized.

If it is a static member, you should set it to zero.

And it is good practice to set the pointers for your classes to zero, too.

struct theStruct
{
    // default constructor
    theStruct() : Class1(0), Class2(0), Class3(0), Class4(0) {}
    MyClass* Class1;
    MyClass* Class2;
    MyClass* Class3;
    MyClass* Class4;
};

Then at time of access, you should check to make sure it is initialized with:

if(theStruct && theStruct->Class1)
    theStruct->Class1->foo();

The ordering of the above if statement does the following: if theStruct is not zero aka, has had new called and is a valid pointer, and if Class1 in theStruct is not zero (also has had new called on it), then use it because it is safe and available.

Hope that helps.

Community
  • 1
  • 1
phyatt
  • 18,472
  • 5
  • 61
  • 80
  • 1
    Actually it's better practice to set your pointers to `nullptr` -> [Why?](http://stackoverflow.com/questions/1282295/what-exactly-is-nullptr) – deW1 Oct 18 '14 at 01:27
  • That's actually a lot of good information for a c++ newbie, also the part where is was declared globally is actually a copy paste error, its local to the MainWindow constructor. I just pass the structure around instead of having a parameter list thats 10+ elements long. – Dave851 Oct 18 '14 at 01:38
  • The difference between a struct and a class is only that by default everything in a `class` is `private`, and everything by default in a `struct` is `public`. Using a `struct` to hold a bunch of common settings or elements is a great way to do it. Qt also supports passing something like this around using signals and slots, but you have to register the custom types. – phyatt Oct 18 '14 at 01:40
  • 1
    @deW1, good point, but it requires use of C++11. I'm still using MSVC 2010 most of the time lately. For those with modern compilers, you can use `CONFIG += c++11` in Qt .pro file to enable use of `nullptr` instead of `0` for your pointers. – phyatt Oct 18 '14 at 01:49
  • @phyatt Funny you mention the slots and signals thing, just ran into QObject::connect: No such slot, MainWindow::updateWebStats(engines). I have this slot listed in the header and implemented in the cpp file, would not regestering my structure then passing it to a slot cause this problem? – Dave851 Oct 18 '14 at 02:20
  • use `qRegisterMetaType("myStruct");` in your main.cpp or in MainWindow constructor. http://qt-project.org/doc/qt-5/qmetatype.html#qRegisterMetaType – phyatt Oct 18 '14 at 02:23
  • Ended up needing to use Q_DECLARE_METATYPE(myStruct) but you put me on the right track, thanks again. – Dave851 Oct 18 '14 at 02:54
0

There appears to be no reason to use a pointer to MyStruct in your example. You should not be using one unless you have some compelling reason to do so, which does not appear to be the case. If you don't use a pointer, you don't need to initialize it in your code with new. It is automatically intialized at compile time, by way of your declaration and definition.

MyStruct theStruct;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    //Build object
    MyClass* firstClass = new MyClass(/*params for object*/);
    theStruct.Class1 = firstClass;

    ui->setupUi(this);
    connect(firstclass, SIGNAL(dataReady()),this,SLOT(updateWebStats(&MyStruct)));
}

See Resource Acquisition Is Initialization for starters. Far too many programmers automatically use pointers in C++ when they are not necesssary at all. Only use pointers when you absolutely need them, and in C++11 use std::shared_ptr and std::unique_ptr whenever possible.

Do not confuse C++ with languages like Java, Delphi, or C#, which require you to allocate classes on the free store and access them only with references/pointers. In C++ you can and should declare stack based variables for class and struct objects.

If there's a better way to do this then a structure, please mention it.

std::vector<MyClass*> might be preferable. See: std::vector:

std::vector is a sequence container that encapsulates dynamic size arrays.

The elements are stored contiguously, which means that elements can be accessed not only through iterators, but also using offsets on regular pointers to elements. This means that a pointer to an element of a vector may be passed to any function that expects a pointer to an element of an array....

Vector
  • 10,879
  • 12
  • 61
  • 101