Search ProofOfProgress Blog

Monday, February 29, 2016

Enforce classes have same static method c++

All my classes must have a method called unitTest in DEBUG mode. This is because I don't want my test code in a separate library.

Separation of concerns is nice and all. But I think that separation also makes it more likely that your test library code will decay.

This might be what I need:

Basically, extend from a header-only class that defines no implementation. And have the function within that class be templated.

Something like:

template< typename T>
    static double foo( vector arr );

In the header, without any implementation.

Can you extend from a class with no implementation? I bet you can. Need to look into that.

Maybe I need a "pure virtual function"?

But that specifies type... Do I need a "pure virtual template function"? That sounds fancy and over complicated.

Yes, you can.

Monday, February 15, 2016

Ownership of pointers in c++ and borrow boxes

Trying to wrap my head around ownership of pointers in c++. Trying to establish rules to make good software. Here are some ideas. 1. Only one object has ownership of any given object. 2. If an object owns another object, when delete[] is called on the parent, it should be called on the child. 3. If an object does NOT own another object, when we delete[] the parent, the other object referenced from within the parent should not be deleted. 4. Any object should either OWN every object it references, or NOT-OWN every object it references. This is to simplify it. So we know exactly what needs to be done to children when delete[] is called. 5. Don't give out references to stuff you don't own. If a class does NOT own the object, it should not be allowed to give out a reference to it. The object that wants the reference should go to the source. ANALOGY: I can't give library book to stranger. The stranger needs to go to the library to get the book I have. Not the best analogy. Since the book they get from the library would also be the book I have. Because we are talking about reference types, not value types. 6. What about classes that absolutely must own some things, but not others? Classes that need mixed ownership must have a "borrow box" or "sandbox" or whatever you want to call it. It is an object OWNED by the parent, so it can be deleted by the parent when the parent is deleted. HOWEVER, the "borrow box" container never owns anything inside it. So when it is destroyed, none of it's contents are deleted. Again, with the rule of not giving out things you don't own... Borrow boxes should never be passed around. A borrow box should not simply be a wrapper you wrap individual objects in. So that you can pass the wrapper around. That wouldn't solve the problem. It would just add another step. The borrow boxes should be taylored to each and every individual class that needs one. No other classes should know about the borrow boxes. So why even have them then? Is it simply a formality that makes the code easier to read? Is it simply a way to avoid individually flagging ownership? It seems like a good idea. But I need more time to think about it. Is it worth the extra -> jump every time you need to reference it?

Sunday, February 14, 2016

Overload = operator c++

I thought I had it... Now all the sudden I am getting the error: error: conversion from 'uint32_t {aka unsigned int}' to non-scalar type 'deathNote' requested... what did mess up??? Solution here: Though I noticed I am having trouble using it with initialization and assignment all in the same line.

Are structs initialized to zero?

Research says that you shouldn't rely on this. Best to include a parameter-less constructor that zeros out all of the member values. The only downside being that it's not longer a POD type by C standards.

object lifetime of structs c++

I know when you want to return a class instance from a function you need to use the new keyword and assign it to a pointer. Is it the same rule for structs? I want my structs on the stack, not the heap. So I'd like to not mess with pointers. But I am afraid doing:
myStruct getStruct(){
  myStruct val;
  return val;
Will the instance of myStruct be killed immediately after leaving the function scope? Turns out, this works with structs. Pretty sure it would not work if it were a class. Also strange is that it seems like... All the members of a struct are initialized? Rather than having whatever random data was there before hand? Or maybe I am just lucky... Might want to explicitly init values by specifying a constructor.

+= operator overloading a struct

Overloading the shorthand addition operator (+=) in c++: Note, this is operator overloading the += operator for a STRUCT. called "deathNote". I follow the constant-class rule for classes. But use lowercase for structs because structs are value-types / primitives. So they should be treated like "int", "float", "char", "string", etc. Which all start with lowercase letters.
deathNote operator_-(const deathNote &a){
    this->apples = a.apples + this->apples;
    this->chocolate = a.chocolate + this->chocolate;
    this->paper = a.paper + this->paper;
    return (*this);

operator+ must take zero or one argument

struct deathNote{

uint32_t apples;
uint32_t chocolate;
uint32_t pages;

deathNote operator+(const deathNote &a, const deathNote &b){
   deathNote ret_val;
   ret_val.apples = a.apples + b.apples;
   ret_val.chocolate = a.chocolate + b.chocolate;
   ret_val.pages = a.pages + b.pages;
   return ret_val;


//ERROR: operator+ must take zero or one argument.
//The fix? One parameter is implied via the "this" pointer.

deathNote operator+(const deathNote &a){
   deathNote ret_val;
   ret_val.apples = a.apples +  this -> apples;
   ret_val.chocolate = a.chocolate +   this -> chocolate;
   ret_val.pages = a.pages +   this -> pages;
   return ret_val;

Saturday, February 13, 2016

Use structs when 16 bytes or under

✓ CONSIDER defining a struct instead of a class if instances of the type are small and commonly short-lived or are commonly embedded in other objects.
X AVOID defining a struct unless the type has all of the following characteristics:
  • It logically represents a single value, similar to primitive types (int, double, etc.).
  • It has an instance size under 16 bytes.
  • It is immutable.
  • It will not have to be boxed frequently.
I think I'll name my structs with lowercase letters.
Constant class... But things like "float", "unit" and other built-in  primitive value types
have lowercase letters. So I'll name my structs with lowercase letters.

How much is 16 byes?
ARGB pixel = 32bits. Each channel is 8Bits. AKA: 32 bit color is 4Byte color.
How many pixels in 16 bytes?
Four. (4+4+4+4 == 16)
So, think of a struct as 4 pixels worth of data or less.

Invalid use of destructor foo as type

Bad Code:


Good Code:


Friday, February 12, 2016

Also useful for memory leak detection in C++

Though mentions having to "redefine" the "new" keyword if using
c++'s new keyword to construct new instances of objects.

Com Vs Crt Leaks

Not sure what this means. But this memory leak detector library for debug builds looks useful.

Thursday, February 11, 2016

Memory Leak Detection, pooling out of scope.

Decided that in my memory leak detection code, I should not try to support
LIVE and IDLE object pools for every single class.
That link together the instances using a linked-list base class.

1. Could get very complicated very quickly.
2. With inheritence, does the base class, or the superclass get to own the object
and have it within it's static linked list?
3. OUT OF SCOPE. This is memory management. We only want to do memory leak detection.

New approach:
All objects inherit from a linked list base class.
There is a MASTER two-way linked list in the C++ project when in debug mode.
If an object from my project exists, it is part of this linked list.

(Only if they are classes, structs do not follow this rule)

1. Using object_ids and parent_ids to confirm object has only one owner.
2. Using MyClass::kill( *instance) methods to manage deletion
3. Using kill_hash checksums to confirm the objects you think were destroyed were destroyed.
4. Using one master linked-list so we can check for orphaned pointers.

I say we have pretty good measures to prevent memory leaks.
Just need to make sure that, when memory leaks are found, we can control the situation.

AKA: I'd rather not find my memory leak by accessing a null pointer.
I'd like to find it by having my memory leak detection code find out about it's existence
in a less hazardous way.

Mem Leak detection Part 2

uint MyClass::deleteInstance(MyClass* c){

    uint deletion_confirmation_hash = 0;
    //Does object OWN it's pointers?
        if(owns != 3){ throw("we may own more or less pointers than this.")}
        uint num1 = OtherClass::deleteInstance(c->ptr01); // 1 //
        uint num2 = OtherClass::deleteInstance(c->ptr02); // 2 //
        uint num3 = OtherClass::deleteInstance(c->ptr03); // 3 //
    deletion_confirmation_hash += c.getObjectID();
    delete c;
    return (deletion_confirmation_hash);

Homebrew memory leak detection.

Having some type of memory leak detection that is only compiled in debug mode I think is a good idea.

NOT memory management. Because that would have to exist in both debug and release.
And memory managers would defeat the purpose of using a high-performance language like C++.

//For a class that has 3 pointers under it's ownership.
//Here is how we could delete it, and get a basic order-independent
//(combination based) hash to confirm the objects we think were deleted
//are deleted.
static uint32_t MyClass::deleteInstance(MyClass* c){

    uint num1 = OtherClass::deleteInstance(c->ptr01);
    uint num2 = OtherClass::deleteInstance(c->ptr02);
    uint num3 = OtherClass::deleteInstance(c->ptr03);
    uint finalNum = c.getObjectID();
    delete c;
    return (num1+num2+num3+finalNum);