Feb 8, 2012

What's wrong with this code - fun with assembly

Since, I'm a bit busy to create new posts I decided to cheat, translating this post from my old (Portuguese) blog :)

Before we continue let me make this clear: finding the actual issue is not terrible hard (even though it took me some time and of course I'll keep the answer to a future post :); the interesting part is to figure it out why it works (or at least, why it works when compiled with some compilers).


Ok, so lets go. Take a look in the following program: 


This program accepts a number (command line) and calculates its factorial.

I came across it while I was corrigindo a programming assignment from one of my students (yep, 14 years ago I used to work as a professor teaching C, C++, assembly and the like).

At that time I used Borland C++ 3.0 to compile and to my astonishment it worked! Last time, when I tried to compile it with VC 6 I noticed a different behavior (the application produced a wrong result) but using Visual Studio 2010 I can reproduce the same behavior as when I first compiled it with Borland C++ 3.0; of course, the compiler generated some warnings which were promptly ignored!


Warning
To ignore compiler warnings is not such a smart idea and of course I'm not recommending you should do it!

Pelo contrário; check all compiler 
warnings in your code and understand the reasons leading the compiler to complain.Do not assume that the compiler has bugs (after all, Select is not broken). If the conclusion is that the code generating the warning is legitimate I suggest you to try to change it, or, in the worst case, disable the specific warning (via #pragma warning) just in the parts of the code that is producing the warning.

int fat(int n)
{
    if (n == 1)
        return 1;
    else
        n = n * fat(n - 1);
}

int main(int argc, char *argv[])
{
     int n = argc > 1 ? atoi(argv[1]) : 5;
     int i = fat(n);
   
     return printf("Fat(%d): %d", n, i);
 }


Have you figured it out already?


See you!

Jan 26, 2012

Interfaces in IL

After a long period of silence, today I've something interesting (IMHO) (and the time to, of course :)) to post about.

Last night I was reading a book about MS IL (intermediate language) when suddenly I stumbled with an intriguing paragraph about interfaces. The "intriguing" part motivated me to write a sample application to test whenever that would be valid in C# or not.
Given the following NUnit test, how can you define a type "IAmAnInterface" so it can pass ?
 
using System;
using NUnit.Framework;

namespace Testing
{
 
 [TestFixture]
 public class BlobPost_Interface
 {
  [Test]
  public void Test()
  {
   var type = typeof(IAmAnInterface);
   Assert.That(type.IsInterface, Is.True);

   var field = type.GetField("fld");
   Console.WriteLine("    Field: {0}", field);
   Assert.That(field, Is.Not.Null);

   field.SetValue(null, 10);

   Assert.That(field.GetValue(null), Is.EqualTo(10));
  }
 }
}

Just in case you missed it, the crux here, is that the test expects IAmAnInterface to be an interface and (and here lies the issue) to define a (static) field! 

How come? An interface with fields?

Well, it happens that the C# specification (and the compiler also!) disallows such constructs, but they are actually valid in IL (as described in Common Language Infrastructure ,session 8.9.4)!

So, in order to get this to work I simply created an assembly in IL (actually I disassembled an assembly written in C# and changed it) that looks like:
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         
  .ver 4:0:0:0
}
.assembly TestString
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                             63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
  .hash algorithm 0x00008004
  .ver 0:0:0:0
}
.module TestString.dll
// MVID: {64C46A76-194E-4608-A835-B41B179AF4FA}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x004D0000


// =============== CLASS MEMBERS DECLARATION ===================

.class interface public abstract auto ansi IAmAnInterface
{
  .method public hidebysig newslot specialname abstract virtual 
          instance int32  get_value() cil managed
  {
  } // end of method IAmAnInterface::get_value
  
  .field public static int32 fld

} // end of class IAmAnInterface


// =============================================================

and referenced it in my C# test application inside VS2010 which happily showed the field in IntelliSense but gave an error when I tried to compile the code (so I resorted to reflection, and it worked) (see picture below):
What do you think?

Best

Adriano

Mar 30, 2011

Do as I say, not as I do

It has been a long time since my last post ...


As usual I have been busy taking care of my kids (if you have two kids you have an idea how much time they require :)), studying, playing with may pet projects and what not.


But something happened and motivated me to stay late and to write this post. To make a long history short, yesterday night I was working on one of my pet projects, binboo (basically a skype plugin that I and other team mates use to add/update issues on our bug tracker) and I spot some code that looked pretty useless to me.


Since I have unit tests (yeah, some of you would argue that strictly speeking they are not unit tests, but anyway, I have automated tests in place) I was not scared of changing the code, so in the next step I just removed the "dead" code running the tests after that. To my happiness, I saw only green in the unit test runner screen. 
Perfect, I though, proud of myself.
After that I just committed my changes and went (happy) to bed only to be embarrassed in our meeting today with an ugly, idiot, ridiculous bug in the exact same code I have touched yesterday. It became clear to me that my unit test coverage can be improved.


After my normal work day I just loaded the project in VS to look at the specific test case that should have failed due to my change but, to my surprise, I had no test case for this particular scenario. Hum... stupid developer.


Lesson learned, I have written a test case before reverting the changes (and of course, I'll study the code to understand why it is required after all).


Ok, let me get back to my other pet projects.


Have fun!


Adriano

Dec 29, 2010

What's wrong with this code (Part XII)

In the last post in this series ("what's wrong with this code") we discussed how db4o's reference system remembers which objects have been stored / retrieved.

In this post I'll show you another piece of code that doesn't always work as the developer expects:

class User
{
   public string Name;
   public User Manager;
   public IList Addresses;

   public User(string name, User manager)
   {
      Name = name;
      Manager = manager;
   }
}

class Address
{
   public string Street;

   public Address(string street)
   {
      Street = street;
   }
}  


using (var db = Db4oEmbedded.OpenFile(databaseFileName))
{
   List<Address> addrs = new List();
   addrs.Add(new Address("Street1"));
   addrs.Add(new Address("Street2"));
   User fooManager = new User("Foo") { Addresses = addrs };

   User fooBarManager = new User("FooBar", fooManager);
   User barManager = new User("John Doe",  fooBarManager);
   User user = new User("Adriano",  barManager);
    
   db.Store(user);
}

using (var db = Db4oEmbedded.OpenFile(databaseFileName))
{
   var query = db.Query();
   query.Constrain(typeof (User));
   query.Descend("Name").Constrain("Adriano");
   
   User user = (User) query.Execute()[0];
   Console.WriteLine(user.Manager.Manager.Manager.Addresses[0].Street);
}

Can you see the problem? No, I am not talking about Law of Demeter "violation" :) (By the way, if you are interested in this subject you can find a nice discussion here).

Again, if you have been working with db4o for some time I am sure you already spent some time debugging this kind of issue.

As always, the answer comes in a future post.

Have fun!

Adriano

May 16, 2010

Installing Nokia SDK on a Windows 7 box

Hi


As you can figure out based on the post title, I want to start to play with Mobile development using Java (no, I haven't gave up on .Net :); it just happens that I own an N95 and I want to write a little application for it1).


After downloading latest Nokia SDK I  tried to follow the steps in the documentation (IDEs for Java Development) but I just get the infamous error:


Cannot start Series 60 SDK for MIDP


while importing the device.


Thanks God, it was just a matter of "googling" for the error message and I got the following page


http://wiki.urban.cens.ucla.edu/index.php?title=Nokia's_Java_Platform_(Carbide.j)


which fixed the issue (I just search in my hard disks and found 5 copies of the offending DLL).


Well, since my daughter has just born I guess this project will run really slowly but I hope it will not stall :) 


Best


Adriano


1. I am planning to write an application that stores information about gym exercises in a db4o database. 





May 11, 2010

Project deployed

Hi


In the latest days I've been really busy with the deployment of the project formerly known as "baby 2.0" (by the way, the official project name is Gabriela). 


Last Thursday (May, 6) my daughter was born with 4.1 Kg and 52 cm. Of course my whole family if very happy and I an my wife are very proud :)


Following you can see some pictures of her:


 


   

That's it for now (I'm gonna to sleep :))

Best

Adriano

Mar 18, 2010

I am not dead. Not yet

Warning: Personal content ahead

I can hear someone screaming already: but it really looked like you have died! :)
Well, you know, I have been having to much work fun lately.

Also, more or less 7 months ago, I and my wife decided to start a new project, daughter 2.0, and since then we have been working hard to get the environment ready to the deployment (there are too many details in such projects deployment). 

At this stage we can say that the project is growing as expected and that we are looking forward to the deployment date.

As always we expect the maintenance phase to consume much more time/resources than the development phase, but we are more than willing to do the required investment so the project will be able to meet its goals; after all, this is our baby :).

Last but not least, as you can see, I am actually alive :). So, bear with me! As soon as I get some spare time I'll do some more posts!

Good to get back to posting!

See you all.