Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site













SourceForge.net Logo

U++ traps and pitfalls

 

Vector<Foo> x;

....

x.At(i) = x[q];

Problem: At invalidates references to Vector; if x[q] gets evaluated first, the reference can be later invalidated by At. (Note: Array does not have the same problem).

Vector<Foo> x;

....

const Foo& s = x.Top();

x.Add() = s;

....

x.Add(x.Top());

....

x.Add(x[0]);

Very similar to above problem, only more explicit.

void MyFn(Array<Foo> x);

This is in most cases a bug - U++ containers have "pick transfer semantics", means that such function destroys the real parameter. (Rarely, however, this can be on purpose).

int x = Null;

double y = x;

C++ knows nothing about U++ Null concept, y will not be a Null. Note that Value is aware about the Null, so this code:

 

int x = Null;

Value v = x;

double y = v;

 

behaves as expected.

#include <CtrlLib/CtrlLib.h>

using namespace Upp;

 

class TestWindow : public TopWindow

{

};

 

EditString es;

 

GUI_APP_MAIN

{

    TestWindow().Run();

}

Warning: You cannot define widgets as global variable. This is rather host platform dependent technical issue rather than deliberate decision.

 

The code might run OK on some platforms, but crash on others. Means, just do not do it...

 

This applies for application static Ctrl's as well. Problem is that Ctrl's may initialize/instantiate only *after* the GUI framework has finished loading and initializing. static or global Ctrl's are usually instantiated before, permanently breaking the GUI init sequence.

 

Solution: use a static method to return an internal static Ctrl.

 

EditString& MyApp::GetEditString()

{

    static EditString _;

    return _;

}

 

Or even better: the Upp Single<> template

 

EditString& es = Single<EditString>();

 

INITBLOCK

{

...

}

 

EXITBLOCK

{

...

}

 

Upp provides a nice solution to do init / deinit work of your package's static or global stuff (i.e. if it's not Plain Ol' Data and needs some function calls).

 

If your INITBLOCK / EXITBLOCK resides in a .cpp file and the file contains code that is actually referenced (used) somewhere else, everything works as expected, no precautions need to be taken. If not, the linker will drop the file, your init code won't be invoked.

 

This is because the INITBLOCK / EXITBLOCK actually registers itself in an init facility from upper Upp code. So no code ref downwards is added.

 

Deprecated Solution:

If nothing else references some code in the file, make it a .icpp file.

 

.icpp files are forced to be linked no matter what. See files description section in manual.

 

Solution:

Use INITIALIZE(MyName); in package header and INITIALIZER(PNGRaster) { .. } in .cpp where INITBLOCK / EXITBLOCK are. Possibly, you can replace INITBLOCK by INITIALIZER body. Including header file into main project ensures that file with INITIALIZER will be linked into binary.

 

 

Last edit by cxl on 12/12/2016. Do you want to contribute?. T++