C++Guns – RoboBlog blogging the bot

29.05.2015

warning: conversion to 'float' from 'int' may alter its value [-Wconversion] (Bug of the day 7)

Filed under: Allgemein — Tags: , , — Thomas @ 22:05

Another bug of the day :D

You can do the following

float var = float(vari); // yes I know I'm loosing precision
int var = int(std::floor(varf)) // yes I know interger can overflow
int var = qFloor(varf) // Qt version

Same for double.

warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

Tricky one. Usually don't use unsigned types. The world is full of negative value. Use signed types.
Except for..
Array index. To access the full 32/64bit address space, one must use unsigned type.

Let variable data be a pointer/array.
data[i] is the same as data+i
Now variable i should have the same wide as data. Which is size_t. Type size_t is 32bit wide on 32bit system and 64bit otherwise.
New rule: Always use size_t for index variable while accessing data. Don't use int.

Type size_t is an unsiged type.
New rule: Never count backwards in for loops while accessing data.

Consider this endless loop
for(size_t i=data.size(); i >= 0; i--)

If i == 0 and i-- then i == 2^32-1 which is > 0. Damn.
There are a lot of solutions. Bad one and really bad ones. Here is my perfect one: You count forward. That is really easy and everybody understands what is going one and there are no surprises.
In the next line you subtract n-i-1 and volia. Perfect.

for(size_t ri=0; ri < data.size(); ri++) { size_t i = data.size() - ri - 1; I named the new loop variabl ri for reverse iterator. Don't forget to add -1. Arrays start by 0. You can of couse use std::reverse_iterator But hey, I love for loops!

2.1GB limit Qt Container (Bug of the day 6)

Filed under: Allgemein — Tags: , — Thomas @ 13:05

Diesmal hab ich mir selbst in den Fuß geschossen. Zum zweiten mal in den selben.

Alle Qt Container können nur maximal 2.1GB allocieren. Das ist eine Design Entscheidung von Qt. Dummerweise wird keine Fehlermeldung erstellt falls man mehr Speicher braucht. Ich kann schon verstehen, dass es irgendwie falsch ist, wenn eine GUI Anwendung auf einmal Tonnen von GB brauch. Aber einfach ein Absturz zulassen ist schlampig.

Warum 2.1GB? Das entspricht der Anzahl der Bytes die ein signed 32bit integer darstellen kann. Genauer 2^31 = 2,147,483,648. Das entspeicht etwas 500 millionen integer Werte. 250 millionen double Werte. Und 83 millionen x,y,z Koordinaten. Das hört sich viel an, aber wenn wir mal ehrlich sind, das ist garnichts. Gerade in der Big Data Zeit rechnet man nicht mehr in GB sondern ehr in PB.

Also, muss man in seiner GUI Anwendung so 10, 20 Zahlen speichern, dann sind die Qt Container alle gut.
Möchte man mehr wissenschaftlich arbeiten, dann nur die std Container. Alles schön trennen und streng zu sich selbst sein, dann stürzen die Programme auch nicht ab :)

20.05.2015

-1 (Bug of the day 5)

Filed under: Allgemein — Tags: , — Thomas @ 19:05

vector vecB;
vecB.resize(vecA.size()-1);

for(size_t i = 0; i < vecA.size(); ++i) {  
  ...
  vecB[i] = value
  ...
}

Na, wer findet ihn?

Bei so etwas findet ich QT's QVector wieder besser als den Standard c++ vector. Qt macht zumindest bei Debug Einstellung eine Bereichsüberprüfung.

Ausser es wird die at() Funktion statt den operator() benutzt. Dann machen beide eine Bereichsüberprüfung. Aber auch hier zeigen sich kleine Unterschiede welche die Philosophie von Qt und cpp Standardlib zeigen.
Qt bietet nur eine cost Version der Funktion at() an. Der Grund liegt wahrscheinlich im intuitiven Verständnis des Codes.
Ein normaler Vector zugriff wie man das seit Jahrzehnten macht geht so:

vec[i] = value;

Das sieht sieht "komisch" aus:

vec.at(i) = value;

Qt für normale Programmierer mit wenig Schmerzen. c++ std für Profis mit viel Schmerzen :D

18.05.2015

2qm2015 Gleisplan

Filed under: Allgemein — Tags: , — Thomas @ 22:05

Hier der aktualisierte Gleisplan. Immer wieder interessant, dass die Gleise in Wirklichkeit etwas anders liegen. Auf dem Plan sieht das so gequetscht aus.

Gleisplan

Gleisplan

Wir haben noch mehr Trennstellen und Kontaktgleise eingebaut um auch einen Blockbetrieb zu realisieren. So soll es möglich sein auf dem 2. Bahnhofsgleis zu rangieren, während auf dem ersten Gleis zwei Züge abwechselnd einfahren können.
Mal sehen ob das auch alles so klappt mit der Automatiksteuerung und dem mikro Relaiscomputer ;)

16.05.2015

integer overflow debugger trap

Filed under: Allgemein — Tags: , — Thomas @ 08:05

Benutzt man 16bit Integer statt 32bit um Speicher zu sparen und seine cache misses zu optimieren, läuft man Gefahr den Zahlenbereich von -32768 bis +32767 zu verlassen. So wie es für Floatingpoint Zahlen Überprüfungen auf over/underflow etc gibt, die ein Signal werfen bzw den Compiler anspringen lassen, so gibt es das auch für Integer. Ist wohl nur nicht so bekannt.

Für den GNU Compiler gibt es die Option -ftrapv [1]

This option generates traps for signed overflow on addition, subtraction, multiplication operations.

Leider wird nicht erwähnt, dass das Programm nun furchtbar langsamer läuft. Weiterhin scheinen sich noch im Geheimen Fehler zu verbergen die ich nicht ganz verstehe. [2]

When -ftrapv is in effect, libcalls are "necessary" so that the results of an operation can be propagated without making the call to the libgcc functions dead.

Im Prinzip funktioniert das Überprüfen auf Overflows aber ohne große Einbüßen wie dieser Artikel zeigt [3]

How much overhead should we expect from enabling integer overflow checks? Using a compiler flag or built-in intrinsics, we should be able to do the check with a conditional branch that branches based on the overflow flag that add and sub set. Assuming that branch is always correctly predicted (which should be the case for most code), the costs of the branch are the cost of executing that correctly predicted not-taken branch, the pollution the branch causes in the branch history table, and the cost of decoding the branch.
...
result in 3% penalty.
...
John Regehr, who’s done serious analysis on integer overflow checks estimates that the penalty should be about 5%, which is in the same ballpark as our napkin sketch estimate.

Der Artikel "Catching Integer Overflows in C" [4] gibt eine schöne Übersicht über die Techniken der Overflow detections und jener FAQ Eintrag "comp.lang.c FAQ list · Question 20.6b" [5] gibt eine Beispiel Implementierung. Mit dieser Einschränkung:

(Note: these functions all share one bug: they may fail if invoked on the largest negative integer, INT_MI

#include < stdio.h >
#include < limits.h >

int chkadd(int a, int b) {
	if(b < 0)
		return chksub(a, -b);
	if(INT_MAX - b < a) {
		fputs("int overflow\n", stderr);
		return INT_MAX;
	}
	return a + b;
}

int chksub(int a, int b) {
	if(b < 0)
		return chkadd(a, -b);
	if(INT_MIN + b > a) {
		fputs("int underflow\n", stderr);
		return INT_MIN;
	}
	return a - b;
}

int chkmul(int a, int b) {
	int sign = 1;
	if(a == 0 || b == 0) return 0;
	if(a < 0) { a = -a; sign = -sign; }
	if(b < 0) { b = -b; sign = -sign; }
	if(INT_MAX / b < a) {
		fputs("int overflow\n", stderr);
		return (sign > 0) ? INT_MAX : INT_MIN;
	}
	return sign * a * b;
}

Nun möchte man nicht für das komplette Programm die Überprüfung einschalten, sondern z.B. nur für 16bit Integer. Vielleicht implementiere ich einen eigenen Type mit überladenen Funktionen dafür. Irgendwann..

[1] https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html
[2] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=35412
[3] http://danluu.com/integer-overflow/
[4] http://www.fefe.de/intof.html
[5] http://c-faq.com/misc/intovf.html

05.05.2015

Relais Flipflop

Filed under: Allgemein — Tags: , , — Thomas @ 22:05

Für das Gleisbildstellwerk brauchen wir Relais, da alles im 60er Jahre Style werden soll.
Ein Flipflop hat zwei gültige Zustände, von denen es hin und her floppt. Wir können ein Flopflop mit nur einem Relais aufbauen, wie es das erste Bild zeigt:

Flipflop1

Flipflop1

Einschalten funktioniert über S1, die Selbsthaltung über K1. Nur wie schaltet man aus? Man zieht einfach das Relais mit S2 gegen Masse. Dazu muss ein Widerstand als Spannungsteiler vor dem Relais eingebaut werden. Das hat mehrere Nachteile:
An dem Widerstand fällt die gesammte Versorgungsspannung an, er muss entsprechen groß realisiert werden und man hat entsprechende Verluste.
Die Spannung des Relais muss niedriger als die Versorgungsspannung sein.

Ein Flopflop mit zwei Relais ist wesentlich eleganter zu realisieren:

Flopflop2

Flopflop2

Eingeschaltet wird mit S1 / S2 und K1 / K2 dient der Selbsthaltung. Aus/Umgeschaltet wird mit dem Öffner Kontakt des jeweiligen anderem Relais. Das nennt man auch eine Schützverriegelung. Da immer nur ein Relais gleichzeitig Spannung haben kann.
Da die Taster ein Umschalten der Relais erzwingen, kann man auch nicht verhindern, dass beide Relais anziehen, wenn man beide Taster gleichzeitig drückt! Das ist natürlich schlecht, da ein Flioflop nur zwei gültige Zustände aus. Aus-Aus oder An-An gehört nicht dazu.
Die Lösung bringt ein weiteres Relais:

Flopflop3

Flopflop3

Die letzte Schaltung ist schon etwas komplizierter. Sie beseitigt nicht nur die angesprochenen Nachteile, sondern bietet zusätlich noch ein Power-On-Reset. Damit wird erreicht, dass das Flipflop gleich beim Einschalten sich in einem gültigen Zustand befindet. So muss es nicht erst nochmal nachträglich resettet werden.

Das Relais K1 hat keinen explizien Schließer für die Selbsthaltung. Es bekommt immer Spanunng über den Öffner von K2 und ist damit im Zweifel das dominante Relais. Beim Anlegen der Spannung zieht also K1 an, hält sich sozusagen selbst und öffnet den Stromkreis von K2.

Beim Betätigen von S2 zieht K2 an, öffnet den Stromkreis von K1 und hält sich schließlich selbst.
Jetzt kommt der erste Witz der Schaltung; Beim Betätigen von S1 zeiht K3 an und schließt den Stromkreis von K1. Gleizeitig öffnet es den Stromkreis von K2 und somit ist die Selbsthaltung von K1 gesichert.

Jetzt kommt der zweite Witz der Schaltung: Werden beide Taster S1 nd S2 gleichzeitig betätigt, gewinnt immer K1. Da K3 immer anzieht und so immer den Stromkreis von K2 unterbricht. Ganz egal was S2 sagt.

Wir haben also eine Schaltung mit 3Bit Speicherkapazität von denem wir nur 1 Bit nutzen. Dafür gewinnen wir eine saubere Umschaltung zwischen den Zuständen ohne die halbe Stromversorgung kurzzuschließen und wir überprüfen die Benutzereingabe. Das Flipflop ist also immer in einem zulässigen Zustand.

2qm 2015 Gleisbildstellwerk 2

Filed under: Allgemein — Tags: , — Thomas @ 11:05

Auf Ebay haben wir ein altes Gleisbildstellwerk ersteigert und ausgeschlachtet. Etwa die Hälfte der Größe müsste uns langen. Mir kam noch die Idee ein Ampere und Voltmeter für je die Haupt- und Bergstecke einzubauen.
So kann man schnell anliegende Spannungen und Ströme kontrollieren, fall die Lok sich mal nicht bewegen will.
Die Instrumente im Bild sind aber noch zu groß. Ich denke so 60x40mm wären besser.

Das Gleisbild selbst passt gut auf DIN A4, wahrscheinlich noch etwas kleiner. So bleibt Platz für weitere Schalten. Denn wir haben extremst viel Funktionalität auf nur 2qm!

Altes Stellpult

Altes Stellpult

Stellpult Testversion

Stellpult Testversion

04.05.2015

storing into constants (Bug of the day 4)

Filed under: Allgemein — Tags: — Thomas @ 17:05

From the Layhey Fortran 95 compiler user guide.

-[N]PCA
Protext Constant Arguments
Compile only. Default npca
Specify -pca to prevent invoked subprograms from storing into constants.

Example
call sub(5)
print *, 5
end
subroutine sub(i)
i = i + 1
end

This example would print 5 using -pca and 6 using -npca.

Greatest bullshit I've ever seen!
They create a compiler who can change compile time constants and make it the default behaviour.

Powered by WordPress