'bug'에 해당되는 글 3건

  1. 2011.04.11 Honeycomb bug on Buffer's have been fixed by Dansoonie
  2. 2011.04.07 Unexpected behavior of Buffers in Honeycomb(Android 3.0) 4 by Dansoonie
  3. 2007.10.07 Absurd Compiler Behavior in Visual Studio 6.0 2 by Dansoonie
My previous post was about unexpected behavior of Buffer's in Honeycomb which seemed like a bug. The bug I found was about float values in cloned read-only FloatBuffer being interpreted differently from the contents in the original FloatBuffer(2011/04/07 - Unexpected behavior of Buffers in Honeycomb(Android 3.0)). I submitted a bug report to Google and it was confirmed as a bug and now fixed internally for future IceCreamSandwich release.

Please refer to http://code.google.com/p/android/issues/detail?id=15994 for more information. My first successful bug report on a commercial product. Yay~

I thank all my colleagues at work who gave me this opportunity and helped me tackle this issue. 
Posted by Dansoonie
I am an android software developer. At work I am developing a 3D GUI framework called Tiffany. OpenGL is used at the core of Tiffany. Like any other OpenGL application, our product uses float type values to define the location(position) of the vertices that consist 3D objects. Therefore, FloatBuffers are used frequently.

Tiffany has been working great until now with all Android versions. However, I recently got a report that Tiffany behaves a bit weird on Honeycomb, that is Android 3.0 which is an Android version for tablet devices. I was able to track down the cause of the problem and found out what was going on with the help of Mr. Shin, whom we think of as a genius. The unexpected behavior was originating from ByteBuffer/FloatBuffer.

In a portion of our code there was something going on like the following.
ByteBuffer byteBuffer =
ByteBuffer.allocateDirect(n*4).order(ByteOrder.nativeOrder())
FloatBuffer buffer = byteBuffer.asFloatBuffer();

//...

//We put some float values in the buffer

//...

FloatBuffer copiedBuffer = buffer.asReadOnlyBuffer();

//...

//use the values in copiedBuffer

//... 


As I was debugging the code line by line, I found out that the values retrieved from copiedBuffer were interpreted incorrectly in Honeycomb. This was a very unexpected behavior as this was working perfectly on previous Android versions.

Here is what was happening. Buffers in Android has a property called Order. This property indicates whether the buffer uses big endian or little endian. In other words it defines how the bytes in the buffer will be interpreted. It turns out that this property is altered in the copied version of the buffer when using asReadOnlyBuffer(). And what is more interesting is that this problematic phenomenon is only spotted when the ByteOrder of the ByteBuffer is specified using the method order(ByteOrder byteOrder) from ByteBuffer.

Here is a simple example which illustrates this problem.

ByteBuffer byteBuffer0 =

ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder());

FloatBuffer buffer0 = byteBuffer0.asFloatBuffer();

buffer0.put(0.1f);

FloatBuffer copiedBuffer0 = buffer0.asReadOnlyBuffer();

Log.d(TAG, "buffer0 endian: " + buffer0.order());

Log.d(TAG, "buffer0[0]: "  + buffer0.get(0));

Log.d(TAG, "copiedBuffer0 endian: " + copiedBuffer0.order());

Log.d(TAG, "copiedBuffer0[0]: " + copiedBuffer0.get(0));


ByteBuffer byteBuffer1 =

ByteBuffer.allocate(4).order(ByteOrder.nativeOrder());

FloatBuffer buffer1 = byteBuffer1.asFloatBuffer();

buffer1.put(0.1f);

FloatBuffer copiedBuffer1 = buffer1.asReadOnlyBuffer();

Log.d(TAG, "buffer1 endian: " + buffer1.order());

Log.d(TAG, "buffer1[0]: "  + buffer1.get(0));

Log.d(TAG, "copiedBuffer1 endian: " + copiedBuffer1.order());

Log.d(TAG, "copiedBuffer1[0]: " + copiedBuffer1.get(0));


FloatBuffer buffer2 = ByteBuffer.allocateDirect(4).asFloatBuffer();

buffer2.put(0.1f);

FloatBuffer copiedBuffer2 = buffer2.asReadOnlyBuffer();

Log.d(TAG, "buffer2 endian: " + buffer2.order());

Log.d(TAG, "buffer2[0]: "  + buffer2.get(0));

Log.d(TAG, "copiedBuffer2 endian: " + copiedBuffer2.order());

Log.d(TAG, "copiedBuffer2[0]: " + copiedBuffer2.get(0));


FloatBuffer buffer3 = ByteBuffer.allocate(4).asFloatBuffer();

buffer3.put(0.1f);

FloatBuffer copiedBuffer3 = buffer3.asReadOnlyBuffer();

Log.d(TAG, "buffer3 endian: " + buffer3.order());

Log.d(TAG, "buffer3[0]: "  + buffer3.get(0));

Log.d(TAG, "copiedBuffer3 endian: " + copiedBuffer3.order());

Log.d(TAG, "copiedBuffer3[0]: " + copiedBuffer3.get(0));


The result in Honeycomb(Android 3.0) AVD would look like the following.

buffer0 endian: LITTLE_ENDIAN

buffer0[0]: 0.1

copiedBuffer0 endian: BIG_ENDIAN

copiedBuffer0[0]: -4.2949213E8


buffer1 endian: LITTLE_ENDIAN

buffer1[0]: 0.1

copiedBuffer1 endian: BIG_ENDIAN

copiedBuffer1[0]: -4.2949213E8


buffer2 endian: BIG_ENDIAN

buffer2[0]: 0.1

copiedBuffer2 endian: BIG_ENDIAN

copiedBuffer2[0]: 0.1


buffer3 endian: BIG_ENDIAN

buffer3[0]: 0.1

copiedBuffer3 endian: BIG_ENDIAN

copiedBuffer3[0]: 0.1


The result in Android 2.X AVD would look like the following.

buffer0 endian: LITTLE_ENDIAN

buffer0[0]: 0.1

copiedBuffer0 endian: LITTLE_ENDIAN

copiedBuffer0[0]: 0.1


buffer1 endian: LITTLE_ENDIAN

buffer1[0]: 0.1

copiedBuffer1 endian: LITTLE_ENDIAN

copiedBuffer1[0]: 0.1


buffer2 endian: BIG_ENDIAN

buffer2[0]: 0.1

copiedBuffer2 endian: BIG_ENDIAN

copiedBuffer2[0]: 0.1


buffer3 endian: BIG_ENDIAN

buffer3[0]: 0.1

copiedBuffer3 endian: BIG_ENDIAN

copiedBuffer3[0]: 0.1

 
So, here is my conclusion. Dalvik uses big endian and Linux which is the operating system I am using at work uses little endian. As a result, ByteBuffers are created to use big endian by default. However, when the ByteOrder is specified to be little endian, the Order property isn't properly copied to the new Buffer in Honeycomb. I suspect that this is a bug in Honeycomb because Honeycomb is the only Android version working differently and also it doesn't logically make sense to use a different endian system to interpret a copied buffer from the original buffer. Moreover, the Order property not being properly copied seems much like a mistake since you cannot set the Order property for FloatBuffers.

I must admit that specifying the ByteOrder of the buffer is an unnecessary step, still Honeycomb's behavior of handling Buffers doesn't make much sense.
Posted by Dansoonie
One of the important roles of a compiler is to notify the coder the number of errors or warnings and their location in the code.
Would anyone disagree?

On Friday, I really got screwed up because of the incorrect stats about the number of errors and warnings in my code, which Microsoft Visual Studio 6.0(VS 6.0 from now on) generated during compilation.

My job is to maintain software, which makes it possible for my colleagues to control the hardware parts that goes in the PDP(Plasma Display Panel) -- I work for a PDP manufacturer. I have to work on 5 different, yet similar versions the program, which I just explained above because we have several product lines depending on the size and resoultion of the panel we are targeting on. This is very very lame since all the programs basically do the same thing. The only differences among them are very minor such as the location of certain variables located in the memory, which the hardware refers to on operation. Poor engineering practice always leads to a disaster !!!
Anyway, I was assigned a job to add a new feature to all the versions. I worked my way and at some point I where I thought I was finished, I pressed the exclamation mark icon to execute the program. VS 6.0 prompt me whether I was going to rebuild the project before I execute it and I chose yes. While the project was being compiled, I was watching the debug window to see if I have created any errors. I got a bunch of warnings about downcasting doubles to ints implicitly and declaring unreferenced variables(none of them from my portion of the code), but I did not see any errors. However, the number of errors and warning, which is displayed at the end of the compilation was indicating that I had a bunch of errors and no warning. And the really exciting(?) part was that the program was executed as if there were no errors. The newly added feature was added in there.
 
Huh ?!@?$#@%#!^*@&%$

How would you react to this situation? What I did was to reconfigure my project settings. This went on for couple of hours switching from project to project but nothing chaged and got worse. After struggling for some time, I finally figure out what was causing this very absturd behavior.

I always copy a project to a new location and do my work there to preserve the original stable version. It is my own way backing up my work and keeping a history. Anyway, the new feature that I added involved the word error. Therefore, the new folder I created to make a copy of the original to work on contained the word error. The word error in the path name for the files were causing the absurd behavior. The word error was replaced with the word 오류, which means error in Korean and the problem was solved.

I have always thought that VS 6.0 had a counter for counting the number of errors and warnings, but I think Microsoft does it somewhat in a perverted way... <- personal opinion.
I think Microsoft counts the number of errors and warnings by parsing the debug window. I'm not saying that parsing would not work. I'm just saying they are doing it wrong and might be doing it inefficiently. Instead of increasing the counter for errors and warnings as they occur during compilation, my guess is that they parse each line of the debug window and searches for the string "error"and "waring" to increment the counter. And it is obvious that they don't parse the full line, but only until they spot either one of the word.

But why? Why did they do it this way? Why Bill?
Posted by Dansoonie