Dec 6, 2015

Applying the Strategy Pattern

One of my favorite patterns, is the Strategy pattern. It is so simple and so useful and can be applied in many contexts.

In this post, I am going to show you where I have applied the Strategy pattern. I've seen many example on the net, mostly academic examples, but in this post, my example will be based on a real world example. I am using Borland Developer Studio 2006 and Windows Vista.

If you not are familiar with the Strategy pattern, there are a  lot of good information out on the net. I will not do any in depth explanation of the pattern here. However, if you are familiar with it, but just don't remember it at the moment, here is the intent of the Strategy pattern according to GoF.

"Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it"

Well, let's start looking into the example I want to show.

Let's say we are working with a program, which is managing items in a stock for a store. The program must handle the items article number, name, weight, price etc.

Now let's say we have some legacy code of a class describing an item.

#ifndef itemH
#define itemH

#include <System.hpp>

class Item
{
public:
 Item(const String &name, const String &artNo,
   float costPriceEuro, float weightKg)
 : name_(name), artNo_(artNo),
   costPriceEuro_(costPriceEuro), weightKg_(weightKg)
 {}

 float GetCostPrice() const { return costPriceEuro_; }

private:
 String name_;
 String artNo_;
 float costPriceEuro_;
 float weightKg_;
};
#endif

Let's say we have a client, which is using the Cost prices. The Cost price can easily be retrieved by calling the items GetCostPrice() method.

Item item("Jeans", "J100-A12", 20.00, 0.450);
float costPrice = item.GetCostPrice();
 
The Cost price is the price the retailer pays for the item. Here we are passing the Cost price to the item via the constructor. The Cost price may have been retrieved from a database or similar.

Now, the new requirements tells us that we must be able to handle other kind of prices. More exactly, it must handle the Gross price and the Net price as well.

Before proceeding, just some explanations of the price terms above. I'm not an economist, so don't be too hard on me. Here are some definitions.

The Gross price is the price after the retailer has added the markup margin and the Net price, is the final price you as customer pays.

 The formulas for the prices can be written according to;

Gross price = Cost price + Cost price x MarkupPercent/100;
Net price = Gross price - Gross price x DiscountPercent/100;

Now it is time to add the functionality to our Item class. The item must know its markup and discount, so we add those two arguments to the parameter list and also adding methods, so the client can get the prices and percentages.

#ifndef itemH
#define itemH

#include <System.hpp>

class Item
{
public:
 Item(const String &name, const String &artNo,
   float costPriceEuro, float weightKg,
   float markupPercent, float discountPercent)
 : name_(name), artNo_(artNo),
   costPriceEuro_(costPriceEuro), weightKg_(weightKg),
   markupPercent_(markupPercent), discountPercent_(discountPercent)
 {}

 float GetCostPrice() const { return costPriceEuro_; }
 float GetGrossPrice() const;
 float GetNetPrice() const;
 float GetMarkupPercent() const { return markupPercent_; }
 float GetDiscountPercent() const { return discountPercent_; }

private:
 String name_;
 String artNo_;
 float costPriceEuro_;
 float weightKg_;
 float markupPercent_;
 float discountPercent_;
};
#endif
 
The details for the metods GetGrossPrice and GetNetPrice is given in the implementation file for the item, see below.

#include "item.h"

float Item::GetGrossPrice() const
{
   return GetCostPrice() + GetCostPrice()*GetMarkupPercent()/100;
}


float Item::GetNetPrice() const
{
   return GetGrossPrice() - GetGrossPrice()*GetDiscountPercent()/100;
}
 
The client then needs to call the methods like below.

Item item("Jeans", "J100-A12", 20.00, 0.450, 110, 25);
float costPrice = item.GetCostPrice();
float grossPrice = item.GetGrossPrice();
float netPrice = item. GetNetPrice();

We now have a situation, which is clearly applicable for the Strategy pattern.

By using the Strategy pattern, we can encapsulate the price calculation in a class, see the definitions below.

#ifndef strategyH
#define strategyH

class Item;

class Price
{
public:
 virtual float Calc(const Item &item) const = 0;
};


class CostPrice : public Price
{
public:
 virtual float Calc(const Item &item) const;
};


class GrossPrice : public Price
{
public:
 virtual float Calc(const Item &item) const;
};


class NetPrice : public Price
{
public:
 virtual float Calc(const Item &item) const;
};
#endif

The implementation file for the concrete strategies, looks like below.

#include "strategy.h"
#include "item.h"

float CostPrice::Calc(const Item &item) const
{
 return item.GetCostPrice();
}


float GrossPrice::Calc(const Item &item) const
{
 float costPrice = CostPrice().Calc(item);
 return costPrice + costPrice*item.GetMarkupPercent()/100;
}


float NetPrice::Calc(const Item &item) const
{
 float grossPrice = GrossPrice().Calc(item);
 return grossPrice - grossPrice*item.GetDiscountPercent()/100;
}
 
Now we have written our abstract base class and the concrete strategies, so let's use them in the Item implementation. First, let's rewrite the Item class definition.
#ifndef itemH
#define itemH

#include <System.hpp>

class Price;

class Item
{
public:
 Item(const String &name, const String &artNo,
   float costPriceEuro, float weightKg,
   float markupPercent, float discountPercent)
 : name_(name), artNo_(artNo),
   costPriceEuro_(costPriceEuro), weightKg_(weightKg),
   markupPercent_(markupPercent), discountPercent_(discountPercent)
 {}

 float GetCostPrice() const { return costPriceEuro_; }
 float GetPrice(const Price &price) const;
 float GetMarkupPercent() const { return markupPercent_; }
 float GetDiscountPercent() const { return discountPercent_; }

private:
 String name_;
 String artNo_;
 float costPriceEuro_;
 float weightKg_;
 float markupPercent_;
 float discountPercent_;
};
#endif

Above, I've written a general GetPrice function, which takes the strategy as a parameter. The corresponding implementation file now looks like below.

#include "item.h"
#include "strategy.h"

float Item::GetPrice(const Price &price) const
{
   return price.Calc(*this);
}

Finally, the client code can be updated according to below.

Item item("Jeans", "J100-A12", 20.00, 0.450, 110, 25);
float costPrice = item.GetPrice(CostPrice());
float grossPrice = item.GetPrice(GrossPrice());
float netPrice = item.GetPrice(NetPrice());

In the future, there may come a new requirement, to implement a new kind of price calculation. In this case, we don't need to modify anything in the Item class, but we need to inherit a new concrete strategy from the abstract base class; Price.

Furthermore, another advantage of using strategies, is showed below. Let's say you need to summarize all GrossPrices and NetPrices of items in a container. Using the first approach with item.GetGrossPrice() and item.GetNetPrice(), may result in two functions, see below.

float GetGrossPriceSum()
{
 float sum = 0;
 //for each item
  sum += item.GetGrossPrice();
 //end loop

 return sum;
}

float GetNetPriceSum()
{
 float sum = 0;
 //for each item
  sum += item.GetNetPrice();
 //end loop

 return sum;
}

These functions are doing the exact same things, except for the function name. We can easily simplify this to one function, using the concrete strategy as an input parameter.

float GetPriceSum(const Price &price)
{
 float sum = 0;
 //for each item
  sum += item.GetPrice(price);
 //end loop

 return sum;
}

I would like to summarize this post with a simple quote from Alan Shalloway/James R. Trott in their book "Design Patterns explained", p. 123.



"Find what varies and encapsulate it"


This is indeed what we are doing in the Strategy pattern. This is something I repeat for myself, when I am designing a new system of my own. Very good to keep in mind.

You are welcome to leave comments, complaints or questions!


Sep 13, 2015

Pass-by-value vs. pass-by-const-reference - Part 2

This is the continuation of the comparison of pass-by-value and pass-by-const-reference. In this post I will do comparison between user-defined classes.

As in my previous post, I'm using Visual Studio 2010 Express in Debug mode and WinDbg to view the disassembly.

First a short catch up what I've done in Part 1. We have added two integers in a function called add.

int main()
{
   int a = 3;
   int b = 7;
   int c = add(a, b);
   return 0;
}

When using the pass-by-value version of add, copies of 3 and 7 were pushed on the stack.

When using the pass-by-const-reference, the memory addresses were pushed on the stack.

This was clearly shown in the memory view of WinDbg.

I'm now going to evolve the add example above a little bit.

Let's say we have user-defined class according to below.

class MyClass
{
public:
   int a_, b_;
};

Further, let's modify the main function.

int main()
{
   MyClass myClass = {3, 7};
   int c = add(myClass);

   return 0;
}

I'm using the same idea as in Part 1. But my add function takes a MyClass type instead of two integers.

First up is the pass-by-value example. Below is the C++ code and the disassembly with the stack.

int add(MyClass myClass)
{
  return myClass.a_+myClass.b_;
}


WinDbg - disassembly of main (about to execute the call instruction) and its stack
Above, we can see that the result is pretty much as the pass-by-value example for the integers in the Part 1. We first initialize the myClass.a_ to 3, the initializing myClass.b_ to 7.
First is 7 (myClass.b_) pushed on the stack, and then is 3 (myClass.a_) pushed on the stack.

The blue and purple frames is the result of the copying, i.e. the push instructions.

Now let's continue with the disassembly of the add function.



WinDbg - disassembly of add function (about to execute the move eax instruction) and its stack
Above, follow the blue and purple lines, and you will see that the add function use the pushed values (i.e. the copies of the original values) to do the calculation.

Finally, it is time to investigate what is going on the the pass-by-const-reference case for our user-defined class.

int add(const MyClass &myClass)
{
   return myClass.a_+myClass.b_;
}


WinDbg - Disassembly of main function (about to execute the call instruction) and its stack
Above, as in the pass-by-value case, the red and green frame sets the variables myClass.a_=3 and myClass.b_=7.

The lea instruction stores the memory address of the first member in myClass, i.e 3 (myClass.a_) in eax, which is then pushed on the stack (blue frame).

Then we are ready to execute the add function, i.e. the call instruction.


WinDbg - Disassembly of add function (about to execute the move eax instruction) and its stack
The move eax, dword ptr [ebp+8] instruction, sets eax to the address of myClass.a_. Next instruction sets eax to the contents of the address which eax points to, i.e. value 3.

Same procedure is done for myClass.b_. The move ecx dword ptr [ebp+8] instruction, sets ecx to the address of myClass.a_. Next instruction add eax (3) to the contents of the address which ecx+4 points to, i.e value 7.

We have finally investigate what is happening for both integers and user-defined classes when using pass-by-value and pass-by-const-reference. When the user-defined classes grows in terms of members, the copying can be very expensive.

You are welcome to leave comments, complaints or questions!

Apr 14, 2015

The ark of programming

The ark of programming. Yes, ark, not art.

This is about the ark of programming and not the art of programming.

This post has a more humorous touch. You have probably heard of the famous "The art of programming" by Donald Knuth. If you don't have heard of it, you have to do your homework and look it up on the internet. I was inspired by this title when I was writing this post.

If you think about it, there are actually a lot of animals hiding in different software development metaphors. During the years as professional developer I have encountered several animals, I will present them all in my ark below.

Bug
Okay. Let's be honest. This may not be a real animal. However, it is a living thing. And it is not wanted on the ark as well as in the code.

Mouse
The mouse is so common, you don't really think about it. I've encountered different schools of mouse using. One school where you use graphical IDE's like Visual Studio, which mouse using is very common. The other school avoid the mouse totally. By using short commands with the keyboard, you don't get slowed downed by reaching the mouse each time you want to open a file, or search for a keyword.

Penguin
Do I need to say more? All Linux developers know what I mean, and probably the rest of you as well.

Python
A very well known programming language.

Bird/Owl
As a developer you can either be an early bird developer or a night owl developer. The first one implies that you are producing better code during the morning and the day, while the latter one implies you are producing better during late evening and nights. Which type are you?

Chicken
Among all weird programming languages, this one is one of the weirdest. The creator must really liked chicken. This language only has one symbol, chicken.

Duck
Do you own a duck? Of course I mean a rubber duck. The rubber duck is excellent if you want to discuss a problem without bothering your colleagues. Just talk to the duck!

Teddybear
Are you doing any pair programming? More specific, are you doing any teddybear pair programming? Teddy bear pair programming is just another way to talk to a mascot, just like the rubber duck. And no, teddybear is not an animal, but bear is.

Monkey
A code monkey is considered to be a skilled developer.

Pig/Chicken
During your daily Scrum, two types of members can be identified, the chicken and the pig. Pigs are totally committed to the project, while the chicken is only involved in the project.

Fox/Dog
Have you ever encountered the sentence; "The quick brown fox jumps over the lazy dog"? It is commonly used when testing encryption for cryptography as well as different text coding standards.

Swan
The black swan event is nothing you want to encounter. A black swan event is an unpredictable event that has a major negative affect on your project planning. It can make your organization or customer very unhappy.

Elephant
I'm sure you know that a string in C++ must be terminated with a NULL character. This character is called a sentinal value, but can also be called "the elephant in Cairo". A sentinal value is a value that ensure a loop or a data structure is terminated.

You are welcome to leave comments, complaints or questions!

Mar 8, 2015

Aggregate initialization

A couple of days ago, I ran into some legacy code, which basically said
Person person = {};
I hadn't really been dealing with this type of initialization before, so I had to look it up. I learned it is called aggregate initialization, and that's the topic for this post. I'm using WinDbg, Visual Studio Express 2010 and compiling in debug mode. Note also that this discussion does not take C++11 into account.

Let's say you have a struct like this.
struct Person
{
   char* name;
   int age;
   bool employed;
};
Before proceeding, we need to know what an aggregate is.
Here is the definition from C++03.
An aggregate is an array or a class (clause 9) with no user-declared constructors (12.1), no private or protected non-static data members (clause 11), no base classes (clause 10), and no virtual functions (10.3).
So the struct Person is an aggregate, which is a condition for the aggregate initialization to work.

So what does this piece of code do?
Person person = {};
I've learned that this initialization says (in this particular case) that all members in the struct will be zero-initialized.

Before proceeding with the aggregate initialization, just a quick note what may happen if you forget to initialize the struct.
The code below, will result in a struct with indeterminate values, and we get a runtime error message when executing the program.

Person person;
printf("%s, %d, %d", person.name, person.age, person.employed);



Well, back to aggregate initialization.

If we execute this piece of code, we will see that the members are zero-initialized.
#include <cstdio>

struct Person
{
   char* name;
   int age;
   bool employed;
};

int main()
{
   Person person = {};
   printf("%s, %d, %d", person.name, person.age, person.employed);

   getchar();
   return 0;
}


Execution of the program above
Above, we say that we initialize Person with an empty initialize-list.

The struct Person can be initialized using a complete initialize-list, see the example below.
 
Person person = { "Kent", 24, true };
printf("%s, %d, %d", person.name, person.age, person.employed);

Execution of the program above

It is also possible to only initialize some of the members, the remaining will be zero-initialized. In the example below, the name- and age-member will be initialized, while the employed-member will be zero-initialized.

Person person = { "Kent", 24 };
printf("%s, %d, %d", person.name, person.age, person.employed);

Execution of the program above

Before ending this post, let's check out the stack from the last example. In the screenshot below, we have just executed the initialization.


Let's clarify what's going on above. The first instruction of interest is at the virtual address 0x009213DE in the disassembly view. As you can see, the struct's Person's name-member is initialized with a 32 bit pointer. This pointer (within the red box) points to the string literal "Kent" (which probably is within a read-only section in the memory).

Further, we see that the struct's Person's age-member is initialized with 18h, i.e. 24.

Finally, the last member in the struct Person, the employed-member, is zero-initialized, using the xor eax, eax instruction.

The stack is shown to the left, as you can see within the blue box, the current stack frame (EBP) start at virtual address 0x0025FA14. The boxes in the stack view shows where the Person's member are located and its values.

You are welcome to leave comments, complaints or questions!

Jan 19, 2015

Pass-by-value vs. pass-by-const-reference - Part 1

You probably already know the difference between pass-by-value and pass-by-const-reference. However, before proceeding, below follows a brief explanation.

Pass-by-value will result in a copy operation, since the function use a copy of the original input parameter. This can be a very expensive operation, especially for user-defined classes with a lot of members (and base classes).

In a function, which use pass-by-const-reference, no copies are used, the function use the original input parameter (but can not modify it, since it declared const).

This post is actually the first post of two, where I'm comparing the disassembly of pass-by-value code vs. pass-by-const-reference code. In this post, the comparison is done with built-in types.

In the next post, I'm doing the same comparison, but for user-defined classes.

I'm using Visual Studio 2010 Express and building in Debug mode. Why? Because I'm demonstrating very simple examples, which means the compiler will do a lot of optimizations in Release mode. Further, I'm using WinDbg to view the disassembly.

Are you familiar with the calling convention cdecl? This calling convention is used by default for each function you are writing in Visual Studio. What you need to know in this context, is that cdecl will put the arguments on the stack in reversed order. It will be clearer when we are stepping through the examples below.

Okay, let's checkout the example. Below is a very simple program which adds two integers. The addition is done in the function add.

int main()
{
   int a = 3;
   int b = 7;
   int c = add(a, b);

   return 0;
}
 
As mentioned above, I'm going to compare the pass-by-value case with the pass-by-const-reference.

First up is the pass-by-value case. Below is the C++ code and the disassembly of the main function with its stack.

int add(int a, int b)
{
   return a+b;
}

WinDbg - disassembly of main (about to execute the call instruction) and its stack
Okay, let's see what's going on above. The first instruction of interest is the instruction in the red frame. Here we set variable a=3. Next instruction (within the green frame) set the variable b=7.

Then we are ready to execute the add function, i.e. the call instruction. But before making the call, we must put the arguments on stack. Remember that the add function use the cdecl calling convention, which means we pass the arguments to the stack in reversed order, i.e. first push 7 (b), and then push 3 (a).

Also note what's occurs on the stack. The red and green frames is the original values of a and b. The blue and purple frames is the result of the copying, i.e. the push instructions.

Now let's continue with the disassembly of the add function.


WinDbg - disassembly of add function (about to execute the move eax instruction) and its stack
Above, follow the blue and purple lines, and you will see that the add function use the pushed values (i.e. the copies of the original values) to do the calculation.

Next up is the pass-by-const-reference case. Below is the C++ code and the disassembly of the main function with its stack.

int add(int &a, int &b)
{
   return a+b;
}


WinDbg - Disassembly of main function (about to execute the call instruction) and its stack

Above, as in the pass-by-value case, the red and green frame sets the variables a=3 and b=7. But after the initiate of the variables, there is a difference. We push two values to the stack, but not copies of the values, but addresses to the values instead.

The first lea instruction stores the address of 7 (b) in eax, which is then pushed on the stack. The second lea instruction stores the address of 3 (a) in ecx, which is then pushed on the stack.

Then we are ready to execute the add function, i.e. the call instruction.

Also check out the stack. The red and green frames is the original values of a and b (exactly as in the pass-by-value case). The blue and purple frames contains the address of b and a (instead of copies as in the pass-by-value vase).

Now let's continue with the disassembly of the add function.


WinDbg - Disassembly of add function (about to execute the move eax instruction) and its stack
Above, follow the blue and purple lines, and you will see that the add function use the addresses of b and a to do the calculation.

The move eax, dword ptr [ebp+8] instruction, sets eax to the address of a. Next instruction sets eax to the contents of the address which eax points to, i.e. value 3.

Same procedure is done for b, which is then added to 3 (a) in the instruction add eax, dword ptr [ecx].

To summarize, in the pass-by-value case, copies of the values are pushed on the stack. In the pass-by-const-reference case, the addresses of the values are pushed on the stack.

In the next part of comparing pass-by-value and pass-by-const-reference, I will have a look at user-defined classes.

You are welcome to leave comments, complaints or questions!

Jan 7, 2015

SOLID

I bet you have encountered some code smells during your programming career.

Maybe you have made a change (corrected a bug) in a module, which caused a change (introduced a new bug) in another unforseen module?

Maybe you have experienced that a very simple change in your module will force you to do changes in multiple modules?

Even worse, code duplicates you wasn't aware of (you fixed a bug in a function in a module, but the bug was not fully solved due an exact code duplicate of the function in another module)?

There are more code smells around out there, you tell me!

However, using SOLID will help you to prevent some of the code smells. SOLID is a set of five basic OOP principles, that will help you to write quality software.

The SOLID acronym:

S : Single responsibility principle (SRP)
   There should never be more than one reason for a class to change

O : Opened/closed principle (OCP)
   Software entities should be open for extension, but closed for modification

L : Liskov substitution principle (LSP)
   Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it

I : Interface segregation principle (ISP)
   Clients should not be forced to depend upon interfaces that they do not use

D: Dependency inversion principle (DIP)
   A. High level modules should not depend upon low level modules. Both should depend upon abstractions.
B. Abstractions should not depend upon details. Details should depend upon abstractions


There is a lot of good articles on the net. I have no intention to explain them here. This post is more of a reminder that there are basic principles to follow.

My personal experienced is that you will need some training to actually understand when to use them. Further you will need some time to make it a habit to always consider SOLID when you are writing software.

Generally, I think it is easier to use SOLID when writing new software. To apply SOLID in existing code demands more effort (and time). Of course, it depends on the code you start from.

You are welcome to leave comments, complaints or questions!

Jan 5, 2015

PE file with empty main()

If you build an empty console program, how many bytes is needed for the Portable Executable (PE)? And what's inside the PE file?

In this post I'm experimenting with an empty console program. I'm reducing the PE file, so it just contains the headers and the binary machine code. I'm using Visual Studio 2010 Express and building the PE files in Release mode. Further, I'm using PE Insider from Cerbero and PEBrowserPro from Smidgeonsoft.

Let's compile and link the following empty program below.
int main()
{
   return 0;
}

A program doing nothing. So simple as it can be. Now, let's check out the size of this program, using file properties.

File properties - size of file


Alright, 6144 bytes of binary data is needed for this empty program. Why is this size needed, and what kind of binary data is in there? Let's fire up PE Insider, and first check out the header size, and then the section table.

PE Insider - size of headers

PE Insider - section table

Above, the SizeOfHeaders present the (HEX)size of the headers, and the SizeOfRawData, present the (HEX)size for each section needed on disk.

Let's try to understand the number 6144. This is actually the sum of the size of the headers and the size of the sections. So let's sum it to verify this:

0x400+0x800+0x600+0x200+0x200+0x200 = 0x1800 (DEC: 6144)

Okay, now we understand why the size is 6144. But what's inside all this binary data?

First let's check out the .text section, i.e. the code. This section needs 0x800 bytes. However, my empty program is doing nothing!

PE Insider - .text section

Above, the .text section starts at offset 0x400 (file on disk), and there is a lot of things going on.

Again, the main function is doing nothing. But there is a lot of other code around in the .text section. It's code from the C Runtime library. For instance, the main function is not the first function called when executing the program, the first function called is the mainCRTStartup function. This is a function in the C Runtime library (and part of the PE file). How do I know this? Well, each program has an entry point, which is specified in one of the headers in the PE file. Let's check it out.

PE Insider - Entry point
 
PEBrowserPro - disassemble view of entry point

Okay, the entry point is at Relative Virtual Address (RVA) 0x12A0 (of course within the .text section). Thanks to the disassemble view from PEBrowserPro, we can see what's going on there. At this RVA, the mainCRTStartup is located.

Next test to do; let's tell Visual Studio to use another entry point (i.e. not the mainCRTStartup). We can do this in the Property Pages dialog.


Visual Studio - specifying my own entry point

After compiling and linking, let's check the file properties again.

File properties - size of file

Wow! The file size is reduced! From 6144 bytes to 3072 bytes. Let's check out the section table again.

PE Insider - section table

Comparing to the screenshots above, the .text section is reduced from 0x800 to 0x200, the .rdata section from 0x600 to 0x200, the .data section 0x200 to 0x000. The .rsrc and the .reloc section remain the same size.

So how do the .text section look like now when we specified our own entry point?

PE Insider - .text section (main entry point)


PEBrowserPro - disassemble view - .text section (main entry point)

The only thing going on in the .text section is the return 0 statement. We have managed to get rid of the C Runtime Library code.

Note that there is a lot of 0's in the .text section. This is just zeropadding, so each section can start at a multiple of 0x200.

Now let's continue with the other sections in the PE file. The purpose for the .reloc section, is to help the loader to do some relocation if the executable not is loaded at its preferred load address. If we remove the DYNAMICBASE switch, the .reloc section will be removed. This means that the executable always will be loaded at its preferred load address, and does not need any relocation information. Let's remove the DYNAMICBASE switch.


Visual Studio - Remove dynamicbase

 Next, compile and link again and check out the file properties, and the section table again.

File properties - size of file
PE Insider - section table

Voila! The file size is decreased from 3072 bytes to 3036 bytes. The .reloc section is gone.

Let's continue with the other sections. What's going on in the .rdata section and the .rsrc section?

PE Insider - .rdata section
 
PE Insider - .rsrc section

Thanks to the ASCII view, we can figure out that Visual Studio embed a manifest in .rsrc section. We can also see that there is a PDB path in the .rdata section.

If we want to get rid of this, we just go to the Property Pages and remove the manifest as well as the debug information.


Visual Studio - Removing manifest



Visual Studio - Removing debugging information

Again, compile and link and check out the file size, the section table, and the .rdata section.

File properties - size of file
PE Insider - section table
PE Insider - .rdata section, remaining data

Not much left. File size is reduced from 3036 bytes to 2048 bytes. The .rsrc section is gone. The .text section contains a couple of bytes of binary machine code and the .data section is empty. There remain some data in the .rdata section. I'm not completely sure what this data is. If you know, please tell me. However, it can be removed by saying no to Whole Program Optimization.


Visual Studio - Whole Program Optimization

Compile and link the PE file and let's have a final look at the file properties and the section table.

File properties - size of file


PE Insider - section table

Well, that's about it! The file size is reduced from 2048 bytes to 1024 bytes. The PE file now just contains the headers and the .text section with a couple of binary machine codes.

You are welcome to leave comments, complaints or questions!