July 6, 2011

C# to C++ Tutorial - Part 1: Basics of Syntax

[ 1 · 2 · 3 · 4 · 5 · 6 · 7 ]

When moving from C# to C++, one must have a very deep knowledge of what C# is actually doing when you run your program. Doing so allows you to recognize the close parallels between both languages, and why and how they are different. This tutorial will assume you have a fairly strong grasp of C#, but may not be familiar with some of its more arcane attributes.

In C#, everything is an object, or a static member of an object. You can't have a function just floating around willy-nilly. However, like all programs, a C# program must have an entry-point. If you have primarily done GUI-based design, you probably aren't aware of the entry-point that is automatically generated, but it is definitely there, and like everything else, it's part of an object. C# actually allows you to change the entry point function, but a default C# project will automatically generate a Program.cs file that looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace ScheduleTimer
{
  static class Program
  {
    /// 
    /// The main entry point for the application.
    /// 
    [STAThread]
    static void Main()
    {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(true);
      Application.Run(new frmMain());
    }
  }
}

static void Main() is the real entry point for your application, which simply initializes visual styles and then immediately launches the form that most C# users are accustomed to working with. Now, we can compare this with a simple "Hello World" C++ program:

#include <iostream>

int main(int argc, char *argv[])
{
  std::cout << "Hello World";
  return 0;
}
This program, to a C# user, immediately looks foreign and possibly even outright hostile. However, almost everything in it has a direct analogue in C#, despite the rather inane syntax that is being used. The most glaring example here is the insertion operator, <<, because almost no one ever uses it except for in streams and the fact that it's in a C++ Hello World program creates an absurd amount of confusion. It's just a fancy way of doing this:
#include <iostream>

int main(int argc, char *argv[])
{
  std::cout.write("Hello World",11);
  return 0;
}

Now, counting the number of bytes you are pumping into the stream is really annoying, and that's what the insertion operator does for you; it properly formats everything automatically. That's all. It's not a demon from hell bent on destroying your life, its just weird syntax. I don't know why they don't also have this functionality in a much easier to understand overloaded function, but there are a lot of things that they don't do, so we'll just have to live with it.

The main() function here serves the same exact purpose as the Main() function in C#. Strict C++ requires you to have a main() function to serve as an entry point, but various operating systems modify it and, in the case of Windows, outright replace it. As such, you will notice that your "hello world" C++ program, when built, opens in a command line. You will learn later how to prevent this by using Windows' proprietary entry function. For those of you familiar with C#, this is exactly the same as C#'s ability to change around the entry point of the application, and you can even make a command line application in C# too by properly changing the compiler settings. The same concept applies to C++, but unlike C#, which defaults to a GUI, C++ defaults to a command line. Changing the compiler settings properly will result in a C++ program that starts in a GUI, just like C# (although unlike C#, C++ doesn't have any help, which turns GUI programming into a complete nightmare).

So now that we have a direct analogue between C# and C++ in terms of where our application starts, we need to deal with a conceptual difference in how C# and C++ handle dependencies. In C#, your class file is just Class.cs, your helper class is Helper.cs, and both of them can call the other one provided they are in the same namespace, or if you are inheriting someone else's, using the correct using statements to resolve the code. If these concepts are not familiar to you, you should learn more about C# before delving further into C++.

C++, on the other hand, does not do behind-the-scenes magic to help you resolve your dependencies. To understand what C++ is doing, one must understand how any compiler resolves references inside code (including C#). When the C# compiler is compiling your project, it goes through each of your code files one by one and compiles everything to an intermediate object code that will later be compiled down into the machine code (or, in this case, bytecode, since C# is an interpreted language). But wait, what if it's compiling Class.cs before Helper.cs even though Class instantiates a Helper object and calls some functions inside of it that then instantiate another Class object? Well, what if you compiled Helper.cs first... but Helper.cs needs Class.cs to be compiled first because its instantiating a Class object inside the function that the Class object is calling! That's a circular dependency! THIS IS IMPOSSIBLE OH GOD WE'RE GOING TO DIE No, it's actually quite simple to deal with. Enter prototypes. If you have the following C# class:

using System;

namespace FunFunBunBuns
{
  class Class
  {
    private int _yay;
    private int _bunnies;

    // Constructor
    public Class(int yay)
    {
      _yay = yay;
      _bunnies = 0; // :C
    }

    // Destructor
    public ~Class()
    {
      _yay = 0;
    }

    public void IncrementYay()
    {
      _yay++;
    }
    
    public int MakeBunnies(int num) // :D
    {
      _bunnies = _bunnies + num;
      return _bunnies;
    }
  }
}

Making "prototypes" of these functions (which C# doesn't have so this will be invalid syntax) would be the following:

using System;

namespace FunFunBunBuns
{
  class Class
  {
    private int _yay;
    private int _bunnies;

    // Constructor
    public Class(int yay);
    // Destructor
    public ~Class();
    public void IncrementYay();
    public int MakeBunnies(int num);
  }
}

Notice the distinct lack of code - this is how circular references get resolved. It turns out that to properly compile your program, the compiler only has to know what a function takes in as arguments, and what it returns. By treating the function as a "black box" of sorts, the compiler can ignore whatever code is inside it. Notice that this applies to constructors and destructors as well - they are simply special functions inside the class. In this manner the entire class can be treated as a bunch of black-box functions that don't actually have any code that needs to be compiled in them. What the C# compiler does is create a bunch of these prototypes behind the scenes and feed them in front of all your code files, so it first compiles Class.cs using a prototype of the Helper class, which allows it to instantiate and use any functions that Helper defines without actually knowing the code inside them. Then, it compiles Helper.cs, compiling assigning code to the previously empty black-box functions defined in the Helper prototype, using a prototype of Class so that it can also instantiate and call functions from Class. In this way, both Helper.cs and Class.cs can be compiled in any order.

But wait, what if Class inherits Helper? In reality, this changes nothing. An important lesson here is that, in C++, you will not be able to simply ignore the fact that everything is a function. Classes are just an abstraction - in reality, inheritance, constructors, deconstructors, operators, everything is just various special functions. Python's class syntax is interesting because requires that all class functions explicitly define the self parameter (which is identical to the this reference in C++ and C#), even the class constructor. Both C++ and C# hide all this from you, so Constructors and Destructors and class functions all magically just work, even though underneath it all they're just ordinary functions with a special parameter that's hidden from view. This is, in fact, how one mimics class behavior in C, which does not have object-oriented features - simply build a struct and make a bunch of functions for it that take a "this" pointer, or a pointer to a specific struct on which the function operates. This behavior can be (needlessly) duplicated using C# - let's transform our Class class to C-style function implementations, ignoring the slightly invalid C# syntax.

using System;

namespace FunFunBunBuns
{
  struct Class
  {
    private int _yay;
    private int _bunnies;
  };

  public Constructor(Class this, int yay)
  {
    this._yay = yay;
    this._bunnies = 0; // :C
  }

  public Destructor(Class this)
  {
    this._yay = 0;
  }

  public void IncrementYay(Class this)
  {
    this._yay++;
  }
    
  public int MakeBunnies(Class this, int num) // :D
  {
    this._bunnies = this._bunnies + num;
    return this._bunnies;
  }
}

Thankfully, we don't have to worry about this, since thinking of class functions as functions that operate on the object is a lot more intuitive. However, one must be aware that even in inheritance scenarios, everything is just a function, or an overload of a virtual function, or something similar (if you do not know what virtual functions are, you need to learn more C# before proceeding). Consequently, our ability to declare function prototypes solves all the dependency issues, because everything is a function.

This is where we get into exactly what the #include directive is for. In C#, all your files are automatically accessible from every other file, and this isn't a problem because compilation is nigh-instantaneous. C++ is much more intensive to compile, partially because it doesn't have a precompiled 400 MB library of crap to work off of, and partially due to a much more complicated precompiler. That means in C++, if you want a given file to have access to another file, you have to #include that file. In our Hello World application, we are including iostream, which does not have a .h file extension on the end for stupid regulatory reasons. However, what about the file our code is in? Our code is not in a .h file, its in a .cpp file. This is where we get to a critical difference between C# and C++. While C# just has .cs files for code, C++ has two types of files: header files and code files.

.cpp == C++ (C-plus-plus) code file
.h = C++ Header file


Header files contain class and function prototypes, and code files contain all the actual code. A C++ project is therefore defined entirely by a list of .cpp files that need to be compiled. Header files are just little helper files that make resolving dependencies easier. C# does this for you - C++ does not. Note that because these are technically arbitrary file distinctions, you can put whatever you want in either file type; nothing will stop you from doing #include "main.cpp", its just ridiculous and confusing. Both #include <> and #include "" are valid syntax for the #include directive, there is no real difference. Standard procedure, however, is that #include <> is used for any header files outside of your project, and #include "" is used for header files inside your project, or closely related to it.

So what we're doing when we say #include <iostream> is that we're including a bunch of prototypes for various input/output stream (i/o stream --> iostream) related classes defined in the standard library, which your compiler already has the corresponding .cpp implementations of built into it. So, the compiler links the application against this header file, and when you use std::cout, it just treats everything in it (including that ridiculously obtuse << operator, which is really just another function) as a black-box function.

Consequently, unless you know what your doing, you should keep code out of header files. C++ doesn't prevent you from throwing functions that aren't attached to classes all over the place, like C# does, so what would happen if you defined int ponies() { return 0; } in a header file that you include in two seperate .cpp files? The compiler will try to compile the function twice, and on the second time it will explode because the function it tried to put code into already had code in it, since it wasn't a prototype! EVERYTHING DIES! So until you get to the more advanced areas of C++, don't put code in your header files (unless you want to watch your compiler die, you monster).

At this point I want to clarify what std:: is, because it looks rather weird to a C# programmer. In C#, the . operator works on everything - you just have System.Forms.Whatever.Help.Im.Trapped.In.A.Universe.Factory.Your.Class.Member.Function() and its all good. In C++, that's not going to work anymore. The :: operator is known as the Scope Resolution Operator. It's a lot easier to explain if I first explain what the . operator has been demoted to. You can only use the . operator on a reference or value type of an instantiated object (basically everything you've ever worked with in C#). The important distinction here is that static functions cannot be accessed with the . operator anymore. This is because Static functions, along with namespaces and typedefs and everything else must use the Scope Resolution Operator. Consequently, you can think of the . operator as being demoted to just calling class functions, and everything else now uses the :: operator. So, std::cout just means that we're access the cout class in the std namespace.

Now we just have one more hurdle to overcome with the "Hello World" application, that funky char* argv[] parameter in main(). Most C# programmers can correctly infer that it is probably an array of some sort, but we don't know what type char* is, other than its clearly related to char.

char* is a pointer. Yes, the same scary pointers you hear about all the time. No, they aren't really scary. In fact, you have been using similar concepts in C# all the time without actually realizing it. First, however, let's take a hard look at what a pointer really is.

Everything in your entire program takes up memory. Since this tutorial is designed for people who know C# already, I really, really hope you already knew that. What you might not know is that all this memory has a specific location on the machine. In fact, on a 32-bit machine, every single possible location of a byte can be contained in an unsigned 32-bit integer. This is why we are currently moving to 64-bit CPUs, because an unsigned 32-bit integer can only hold up to 4294967295 possible byte locations, which amounts to 4.2 gigs of memory. That's why you are limited to 4 gigs of RAM on a 32-bit machine, and windows has difficulty using more than 2 gigs because a lot of older programs assumed that a signed 32-bit integer was sufficient for all memory addresses, so windows has to do some funky memory paging techniques to get programs that ignore the last bit to use memory locations above 2147483647.

So, if you allocate a float, either on the stack or on the heap, it must exist somewhere within those 4294967295 possible byte locations. Consequently, lets say you want to call a function that modifies that float, but the function has to have a void return value for some arbitrary reason. If you know where in memory that float is, you can tell the function where to find the float and modify it to the desired value without ever returning a value. Here is an example C++ function doing just that (which is syntactically valid all by itself because C++ allows functions outside of classes):

void ModifyFloat(float* p)
{
  *p = 100.0;
}

int main(int argc, char* argv[])
{
  float x = 0; //x is equal to 0.0
  ModifyFloat( &x );
  // x is now equal to 100.0
}

What's going on here? First, we have our ModifyFloat() function. This takes a pointer to a float, which is declared by adding a * to the desired type we want to make a pointer to. Remember that pointers are really just 32-bit integers (or 64-bit if you have a 64-bit operating system), but C++ assigns them a type so that if you try to assign a double to a pointer to a float, it throws an error instead of overflowing 4 extra bytes, causing a heap corruption and destroying the universe. So char* is a pointer to a char, a double* points to a double, and Helper* is a pointer to our own Helper class.

The next thing done in ModifyFloat() is *p. In this case, the * operator is the dereference operator. So unfortunately * is the multiply, pointer, and dereference operator in C++. Yes, this is retarded. I'm sorry. But what the heck does dereference even mean? It takes a pointer type and turns it into a reference. You already know what a reference is, even if you don't realize it. In C#, you can pass a variable of your Helper class into a function, modify the class in the function, and the original variable will get modified too! This is because, by default, classes are passed by-reference in C#. That means, even though it looks identical to a variable passed by value, any changes made to the variable are in fact made to whatever variable it references. So, this idea of passing variables in by reference should be familiar to an experienced C# programmer. C++ has references too, I just haven't gone over their syntax. Here's a more explicit version of the function:

void ModifyFloat(float* p)
{
  float& ref_p = *p;
  ref_p = 100.0;
}

This is the exact same as the previous function, but here we can clearly see the reference. In C#, if you wanted a variable normally passed by value, like a struct, to get passed by reference, you had to override the default behavior by adding ref. In C++, a variable that is a reference to a given type is declared in a similar manner to a pointer. The & operator is used instead of *, so in this example, float& is a reference to a float. We assign it to the value produced by turning our pointer into a float reference. Then we just set our reference equal to 100.0 and it magically alters the original variable, just like it would in C#. In fact, here is the same function written in (slightly illegal) C#:

public static void ModifyFloat(ref float p)
{
  p=100.0;
}

This does the same thing, just without the pointer. In fact, we can totally ignore the pointer in C++ too, if we want (which I tend to prefer, when possible, because its a lot easier to work with):

void ModifyFloat(float& ref_p)
{
  ref_p = 100.0;
}
int main(int argc, char* argv[])
{
  float x = 0; //x is equal to 0.0
  ModifyFloat( x );
  // x is now equal to 100.0
}

Now, in this implementation, you will notice that our call to ModifyFloat is now equivalent to what it would be in C#, in that we just pass in the variable. What happened to that random & operator we had there before? The & operator is also known as the address-of operator, meaning when its applied to a variable as opposed to a type, it returns a pointer to that variable (yay, more context-dependent redundant operators). So, we could rewrite our function as follows to make it a bit more clear:

void ModifyFloat(float* p)
{
  float& ref_p = *p; //get a reference from the pointer
  ref_p = 100.0; //modify the reference
}
int main(int argc, char* argv[])
{
  float x = 0; //x is equal to 0.0
  float* p_x = &x; //get a pointer to x
  ModifyFloat( p_x ); //pass pointer into function
  // x is now equal to 100.0 
}

As we can see, pointers are just the underlying work behind references. If you ever go into Managed C++, you'll find out that all C# references are really just pointers, but the language treats them as references so they're hidden from you. In C++, you can have both pointers and references. It is important to note that you can only initialize a reference variable. Any subsequent operators will be applied to whatever variable its referencing, making it impossible to get the address of a reference variable or do anything to the reference variable itself - for all intents and purposes, it just is the variable it references. This is why pointers are handy - you CAN reassign the actual pointer variable while also accessing the variable its pointing to. Consequently, you can also get the address of a pointer variable, since just like any other variable, including the reference variable, it must occupy memory, and therefore has a location that you can get a pointer to (we'll get to that syntax in a minute). But there's one more thing...

What about arrays? In C#, arrays are actually a built-in class that has lots of fancy functions and whatnot. Interestingly, they are still of fixed size. C++ arrays are also fixed size, but they are manipulated as raw memory. Let's compare initializing an array in C++ and initializing an array in C#:

int[] numbers = new int[5];
int* numbers = new int[5];

It should be pretty obvious at this point that arrays are pointers in C++. I can even rewrite the above in C++ using an empty array syntax, and it will be equally as valid:

int numbers[] = new int[5];

int x[] is identical to int* x. There is no difference. Observe the following modification of our original Hello World function:

int main(int argc, char** argv);

Same thing. In fact, if you watch your compiler output carefully, you might even see the compiler internally convert all the arrays to pointers when its resolving types. Now, as a C# programmer, you should already know what arrays are. You should probably also be at least dimly aware that each element of an array occupies memory directly after the element proceeding it. So, if you know where the address of the first element is, you know the second element is exactly x bytes afterwards, where x is the number of bytes your type takes up. This is why pointers have types associated with them - we know that float* points to an array of elements, and that each element takes up 4 bytes. To verify this, the sizeof() built-in function/operator/whatever will return the number of bytes a given type, class, or struct takes up. That's the number of bytes we skip ahead to get to the next element in an array. This is all done transparently in C++ using the same array index operator as C# uses:

int main(int argc, char** argv)
{
  int* ponies = new int[5];
  ponies[0] = 1; //First element..
  ponies[1] = 2; //Second element...
}

So pointers can be treated as arrays that behave exactly the same way a C# array does. However, the astute C# programmer would ask, how do you know how long the array is?

YOU DON'T


Enter every single buffer overflow error that has been the bane of man since the beginning of time. YOU have to keep track of how long the array is, and you'd better be damn sure you don't get it wrong. Consequently any function taking an array of variable size will also require a separate argument telling the function how many elements are in the array. Usually arrays are just constructed on the stack with a constant, known size, which is often harmless and pretty hard to screw up. If you start doing funky things with them, though, you might want to look up std::vector for an encapsulated dynamic array.

So C++ arrays are just like C# arrays, except they are pointers to the first element, and you don't know how long they are (and they might cause the destruction of the universe if you screw up). You should already know that a string is an array, and consequently in C++ the standard string type is const char*, not string. You also can't put them in switch() statements. Sorry.

There's a lot of stuff about pointers that this tutorial hasn't covered, like function pointers and pointer arithmetic, which we'll get to next time.

Part 2: Pointers To Everything

June 19, 2011

On Hacking (or Why We Need Security Ratings)

Another website has been hacked. It seems almost routine now, with site after site getting demolished by hackers. The overwhelming public response to the catastrophe has been to ask, "can anything be made secure?" Security experts, naturally, are constantly attacking the companies in question for their dismal security practices, but what of the general public? They don't know what a hash is. They don't know what an SQL injection is. They have no reason to know these things and will never understand them. All they understand is that their company assured them they had good security, and then they were hacked, and somehow the good security wasn't actually good. So then they'll move to another company, and this time, they're told, this company really does have good security. But nope, it got hacked too, guess that good security wasn't actually good.

Can any security be good? A security expert knows why the companies were hacked and can answer that question - the average Joe probably won't be able to. This is the crux of the problem - What is good security? How can an average person figure out what good security is? Good security used to be MD5 hashing. Then it was MD5 hashing with a seed. Now MD5 is cryptographically insecure, so we're trying to move to SHA1, but even that might be crackable in the near future, so someone invented bcrypt, but now the bcrypt implementation has demonstrated some unnerving behavior, making its implementation unverified. Then there is SQL injection vulnerabilities and the long list of XSS attacks, along with cookiejacking made possible by unencrypted networks and Firesheep. Even now we are seeing weaknesses at the highest echelons of security - hacked RSA databases and even HTTPS certificates.

Answering our question of what good security is clearly isn't easy. Of course, what if we assume that all security is broken? We would have to outlaw all hacking and seriously punish the offenders because there is nothing that can be done to lock up the system. This approach, however, is inherently flawed. For one, it is closely related to the drug war waged by the U.S. authorities, which has been astoundingly ineffective at stopping the drug trade. Not because it can't shut down drug-rings (it's very good at doing that), but simply because the business is so profitable that for every player you kill in the game, another one crops up to take their place. Lulzsec serves as a harbinger of that scenario, where hacking is cheap, and even if you throw everyone involved in jail, someone else will replace them.

However, even this scenario is being optimistic. If security is near impossible, computers become useless. The real world would turn into Hollywood, where electronics are easily bypassed. The problem is that if computer security is easily bypassed, people will stop using it. Online transactions die. The paper trail comes back. People refuse to put their personal details in anything that could be digitized. Everything that has enabled the technological explosion of today would get stuck in a tug-of-war between security and convenience. If history is anything to go by, the public would rather give up the last bits of their privacy just so they could use all the conveniences of electronics without having to worry about hackers. Suddenly we live in 1964.

This scenario may seem implausible to you because it is. Computer security can be effective, it simply needs to be done properly, which is not impossible. It may be difficult, but so is starting a successful company, and that doesn't seem to stop any of the entrepreneurs. The problem we face is that the average customer has no way of discerning good security from bad security. If they could, market pressures would force companies to adapt the best security possible, or customers would take their data elsewhere. Security is crap because no one knows what security is other then the security experts.

We have building inspectors and elevator certifications and health inspectors... why not security inspectors? It doesn't need to be government mandated, considering the government's track record, it might be a lot better if a private company or group provided the service, but somehow, there needs to be a way to measure security in a verifiable manner. There are two ways I know of to do this (there may be others) - from the inside, and from the outside. An inside inspection is more reliable when done properly, but more likely to be corrupted and gamed. An outside inspection, however, doesn't rely on the consent of a company to plaster a security rating on them. The downside is that an outside inspection requires pummeling the company's product blindly, which will only catch the really stupid mistakes, and not the dangerous middle-ground between really bad security and really good security.

I'm not pretending I know how to solve this problem. I don't, but I do know that someone needs to figure this out. If we are going to make any headway with security, the general public needs a friendly, easy, intuitive way to check the security rating of a company, instead of relying on the company's insistence that it uses a "very sophisticated security system". Only then will market pressures push for the resurgence of proper security.

June 8, 2011

My Mom Had a Heart Attack

She is fine and will make a full recovery.

About 3 weeks ago, on Thursday, May 19th, at approximately 6 PM, my mom went into ventricular fibrillation and collapsed while walking on a nearby trail. She was found by two walkers who called 911 and initiated CPR. After almost a half hour of CPR and 3 defibrillator attempts, she was stabilized and taken to the nearby hospital. She had no identification, so we didn't know about it until after 2 hours of failed searching, at which point my dad called the local hospital.

As I was taken to see her while in critical condition, we didn't know if she was going to survive, or if she did, if she would have serious brain damage. A lot of things went through my mind on that car ride, but the one that was the most striking was when I realized that my inability to achieve what I had been trying to do for so long could potentially mean the last thing my mom was mentally capable of processing would be a son who had simply tried to accomplish something. Who had tried very hard, but hadn't actually managed to do anything of significance. My life was simply a lot of determination, a lot of talk, a lot of failures, and no results. I was still in college, I still didn't have a company, I didn't even have a job, and I still hadn't brought any of my more spectacular ideas to fruition. I was almost 21 years old, my mom had almost died from a heart attack, and I hadn't actually done anything.

The next day my dad called "just about everyone" to tell them what was going on, which indirectly resulted in me being reunited with one of my old friends. Due to my mom's condition in the ICU, she had little to no short term memory, and so every day when I went to visit her I would tell her that my best friend from forever ago had visited, and every day (once the breathing tube was removed), she would react with surprise. She was very confused and kept asking about why she was in the hospital. It turns out this was a pretty good question.

They did a CT scan of her chest to see if she had any blockages or other potential threats to her heart, and discovered that her arteries were entirely devoid of plaque buildup, and she appeared to be almost perfect health, aside from the fact that her heart suddenly stopped working for what appeared to be no reason at all. The only connection we could find was that a similar event happened to my grandfather (her father) at almost the same age. While he also passed out, his episode was caused by atrial fibrillation. She has since had a miniature pacemaker of sorts installed that will automatically deliver a defibrillator shock if the event ever occurs again, but it raises questions about whether the condition is hereditary.

If this is some kind of strange genetic disorder, it carries the lovely news that even if I'm in perfect health in 30 years, my heart could get a random bad signal from my brain for absolutely no reason at all and I could keel over and die if no one happens to notice me pass out. Luckily I don't have to worry about that until I have kids in elementary school.

Thankfully my mom is back home and, aside from some minor lingering medications and precautions, has fully recovered. Unfortunately, I still haven't done anything.

June 3, 2011

The GPL Sucks

When I release an open-source program, I want to guarantee something very simple. The program and its source code can be distributed and used by anyone for any purpose, and all modifications to the program must be released as open-source under these same terms. I want to guarantee that the program and any improvements made on it are available to anyone, proprietary or not, forever.

This is impossible.

Why? Because the GPL specifically states that any code used in a GPL project must be under a GPL license. The GPL is written in such a way so that your code must somehow be able to be converted into GPL-licensed code if it is to be used in a GPL project. This doesn't really seem to be a problem, at first, until you start thinking about what it means for code that is designed to be used by ANYONE, including commercial ventures. Lets say I write a program under the BSD license. Some guy can run along, fix a bunch of bugs for me, but release those bugfixes under the GPL, preventing me from using any of them in my program unless I'm under the GPL. This even happens if you release under the LGPL, because LGPL code can be converted to GPL and, whoops, you can't get it back!

This is just as bad as a company taking my code, fixing some bugs, and making those bugfixes proprietary. Both sides of the fence are excluding the other side of the fence, and explicitly prevent me from trying to straddle both sides. The free software foundation is making it impossible to be neutral. Either your with them, or you are against them. This is stupid.

This might be good for free software, but not for open-source software. The GPL destroys the entire point of open-source software - contributions from outside sources provide substantial improvements. The GPL's viral nature dissuades people from using it because it acts to the exclusion of everything else. A company has zero motivation to help improve GPL'd software because they can't benefit from their improvements. On the other hand, if open-source software was open-source for the purpose of being open-source instead of for free speech, we'd have companies who could legally use open-source software and consequently improve on it, and be required to release these improvements to the open-source community, to the benefit of everyone.

But of course, free software is about freedom of speech, and so we come to the unfortunate conclusion that, should free software continue its misguided crusade, the ideal open-source project will be fundamentally incompatible with free software, and so free software and open-source software will inevitably diverge into two parties with mutually exclusive goals.

And to think that all I want to do is guarantee that everyone can use my code and benefit from all improvements made to it. But I guess people don't care about that, they only care about whatever cause they might be fighting for, instead of mutual co-operation for the benefit of humanity. Since, apparently, I'm against free software, because I want to share my code with everyone, instead of only people who agree with me.

Great. Is this really what Free Software stands for? Is this what you want it to stand for? If it is, I'm afraid I simply can't support something that forbids compromise. Progress requires compromise. This is unacceptable.

EDIT: It is truly amazing how many ways people manage to misinterprete or flat out not read my blog post. This is not the GPL, the LGPL does not work, I am not championing any BSD-related licenses, and my comment about companies was directed at proprietary software. Of course Redhat makes a profit off the GPL, its business model is compatible with it.

Perhaps I will try again at some later date with a blog post that spends less time actually explaining what I'm talking about and more time preventing people from latching on to completely irrelevent points.

The Logical Basis of Ethics

In modern times society has come to understand that some moral standards are unfair - Most people agree that racism is unfair and should not be tolerated. What is interesting is that almost any given ethical system will be considered unfair only if it is logically inconsistent. That is, an ethical system is fair precisely because it is logically consistent with itself. While racism is commonly considered unfair because thinking another human being is inferior to oneself based on some arbitrary physical attribute makes no sense, the entire concept of a superior race being allowed to make another race suffer is logically inconsistent. This, in turn, leads us to the problem of animal rights.

It is generally accepted that humans are superior to animals, at least for the sake of moral consideration. This is usually rationalized by a number of logical reasons, such as a sentience, or simply that any creature has a right to favor its own species over another. While this is a common aspect of several environmental ethical structures, it isn't necessary. It is a known fact that some people respond well to vegetarian diets, while others suffer from serious nutrient deficiencies. This is because humans are omnivores; we do not eat vegetables OR meat, we eat vegetables AND meat. We usually require both to remain healthy, although some individuals can successfully short-circuit this. However, it only justifies killing the animal for the purposes of a food source, not for torturing, poaching or other activities that are, coincidentally, illegal. We are therefore obligated to make an animal's death as painless as possible - something PETA has repeatedly brought up in its war against factory farming.

Factory farming itself is obviously immoral as it involves inflicting substantial amounts of suffering on animals that are then slaughtered. One can say its immoral for all the reasons PETA loves, usually involving graphic pictures of mistreatment, but we are more interested in the fundamental aspects of an ethical system. Specifically, a logically consistent ethical system can be constructed using only two postulates: Living things can suffer, and living things don't want to die. More accurately, the ethical system only applies to things that can suffer and things that have a survival instinct. From these postulates, we can formulate two simple theorems: One should not cause unnecessary harm, and one shouldn't kill unless necessary. From this, it is obvious that PETA is, surprisingly, correct - Factory farming is inescapably immoral. Unfortunately, things are never that simple.

The problem with factory farming is that almost the entire meat industry relies on it, all across the world. If it was made illegal, it would simply be done illegally, or the entire world meat industry would collapse and things would really, really suck. This kind of suffering is unnecessary, but it would be more accurate to come up with a new theorem: One should minimize the amount of suffering. This is why factory farming still exists and why we ignore what is clearly an immoral situation - there is no current alternative. PETA, in a brief flash of sanity, recognized this and has since been pushing for better treatment of the animals in the factories; but even this has problems. While there is obviously widespread animal mistreatment, there is also widespread rape, murder, extortion, bribery, theft, bullying, racism, sexism, anything-ism, homophobia, poaching, global warming, lying, hate crimes, harassment, trolling, abuse, etc. etc. etc. There is literally so much stuff going wrong that fixing factory farming simply isn't a priority right now, and so we end up in a case where an obviously immoral act must be tolerated for the sake of practicality. At some point in the future when we have presumably reached a more utopian society, we will be able to make fixing this a realistic priority. Clearly, the simple fact that something is immoral does not paint a black and white picture. Life is always a shade of gray.

This, of course, brings us back to racism. Racism is commonly discarded as an invalid belief because you can't assume that you are better than someone else just because they're skin color is different. What this ignores is the more fundamental question - what if you are better than someone else? Most moral systems try to do away with this by invoking the standard equality statement, "All men are created equal". This, unfortunately, does not really solve any problems. Is Albert Einstein on the same level as a hobo on the street? For the sake of the general public, the answer is usually yes, because considering everyone as an equal simplifies an ethical system greatly. Unfortunately, it stops working with things like animal rights. However, our previous two postulates can be brought to bear on this situation, because we know that one should not cause unnecessary suffering. Just because you are somehow superior to someone else does not give you a right to do anything to them. The only reason we are allowed to herd cattle for slaughter is because we require sustenance. Consequently the fundamental idea of racism is totally flawed - even if, by some insane, misguided logic, black people were on the same level as animals, it doesn't actually justify jack shit. Slavery would still be immoral. Discrimination would still be immoral. All of this stuff is still immoral. Racism is not only wrong between human beings, its wrong for anything. Being better than something else does not let you torture it.

Our modern day equivalent to racism is same-sex marriage. There are still a large percentage of the population that maintain that homosexuality is immoral. This is logically inconsistent, and surprisingly a lot of arguments used against homosexuality can actually be proven to be logically inconsistent, and therefore unfair. Many people state that homosexuality is unnatural and therefore bad. The common response to this is that homosexuality is present in nature and therefore not unnatural, but this ignores the more fundamental assumption that something unnatural is bad. This assumption can be proven false using proof by contradiction: Someone has a heart attack. A defibrillator is used to restart their heart and they go on to lead a happy, fulfilling life. The defibrillator is obviously very unnatural, but it prevented loss of life. Preventing loss of life is inherently moral because all beings that this moral system applies to have a desire to live. Consequently something unnatural cannot be inherently bad.

But what if same-sex marriage is against your religion? This line of thinking doesn't work for several reasons. For one, someone can simply invent a religion where your existence, and only your existence, is against the religion and therefore you must be killed. More fundamentally, however, you can't force your religious convictions on someone else, unless someone is using your religion to deliberately harass you, which is a problem of harassment, not religion. Consequently if someone needs to draw Muhammad to make a political point, you have to let them do this even if its insulting to your religion because they aren't deliberately trying to make you suffer, and so if you oppose them you are instead forcing your own religious opinions on them, which simply does not make any sense, because anyone can have a religion that does anything they want. You must have a better reason than "its against my religion", like "that is a deliberate attempt to aggravate me". Ironically, this same line of thinking is why someone is allowed to not say the pledge of allegiance if its against their religion. It isn't because its against their religion, its because they simply chose to not say the pledge, and not saying the pledge doesn't cause harm to anything, and therefore cannot be forbidden for any ethical reason.

This idea of something not causing harm to anything else is the basis for a famous ancient moral system, "If you harm none, do what you will". This has to be inferred from our two ethical postulates, because all our postulates state is that one should not cause harm or kill things. However, it is the very fact that these are the only postulates that lead us to this new inference - you can't use the ethical system to prevent someone from doing something if that something doesn't harm anything. You can try to justify it using some other system, but the ethical system will not allow you to make a valid logical argument against an action if that action doesn't cause unnecessary harm.

The fact that ethics are inherently based on logical consistency suggests that a sort of Ethical Calculus should, in fact, be possible. While one constructs the basis of an ethical system on moral absolutes, (do not kill or cause suffering), this foundation is given a qualifier, "unless necessary". The complex interactions that arise from minimizing suffering are what form the complex relative moral systems that govern our higher-order ethical considerations. Like economics, moral relativism exists because the absence of suffering is a scarce resource. This relativism, however, is formed from a logical basis, and so can be represented by an abstract logical system and analyzed as such. Perhaps a system of Ethical Math will one day allow us to quickly decipher the best ethical course of action, or failing that, what exactly makes a given ethical situation so complex.

Besides, if ethics are logical, and computers can evaluate logical statements, what is stopping us from making ethical AI?