torkell: (Default)
Today's programming silliness: creating a function with 16 parameters.

And then creating a second function with 39 parameters to call the first one.

The worst part: I think it makes the code more readable!
torkell: (Default)
What with the glorious sunny weather, I wondered how hot my flat actually gets. It's certainly felt far too warm recently.

Now, the sensible way to find out is to go and buy a thermometer. But Robert Days are closed for the evening. So instead I dug out an Arduino kit I was given for my birthday (Elegoo's "The Most Complete Starter Kit for the Mega 2560") and set to work...



The answer: 27°C!

Code! )
torkell: (Default)
If you do software development then you've probably had the misfortune of working with Git as a source control system. Now, those of you who use Git will be aware that it makes very heavy use of branches, and that it's all too easy to end up with a whole pile of them of of which are the one that you actually need.

Well, it turns out it's all very simple after all, as this image that dropped into my work inbox reveals:



You could tell the email's progress around the office by when different people burst out laughing.
torkell: (Default)
Today's discovery is working out just how to configure Eclipse so that it actually finds the correct headers for a C++-based project I was poking at. This is hard enough most of the time but in this case it's cross-compiled with a MinGW-based GCC and a custom Makefile, and Eclipse CDT helpfully doesn't tell you that autodetecting the config failed.

No, this isn't the NAS I was poking at a few years back - that I solved by getting a slightly newer NAS with a more complete Linux install including compiler. Today's target embedded system is a 3DS, using the devkitARM toolchain.

Anyway the answer was surprisingly easy but not at all intuitive: in the project properties go to C++ Build and on the Builder Settings tab tick Generate Makefiles automatically but don't apply the change yet. Then go to C++ Build → Settings and a new Tool Settings tab will be visible. Select Cross Settings and fill in the correct path and prefix (including the trailing hyphen, so something like "arm-none-eabi-"). Finally go back to Builder Settings and untick Generate Makefiles automatically, and now you can apply the changes. Right-click on the project, pick Index → Rebuild and all the broken includes should sort themselves out.

That solved most of my problems but still left Eclipse whining about some unresolved includes. That turned out to be because the code I was looking at wanted a newer C++ standard - to fix that go through the rigmarole to make Tool Settings reappear and under Cross G++ Compiler → Dialect pick the appropriate standard. Or if the one you want isn't listed, then enter the option in Other dialect flags (for devkitARM I needed "-std=c++14").

I still had to manually add the header path for libctru and a couple of defines that were in the Makefile, but that's fair enough - it's getting the system headers all sorted that's the hard part!
torkell: (Default)
Because I can't be the only person who's run into this: I think I've found a bug in Windows 7 where icons can disappear from the system tray if an application hides and then unhides an icon. It appears that Windows doesn't rearrange all the icons (as it does when a program adds or deletes an icon), but instead just moves the icons in that row along one space. If you've got more than one row, then you end up with an empty space at the end of that row... which Windows will happily fill with another icon. If the original icon is then unhidden then it pushes the new one off the end of the tray and it disappears from view entirely.

It's most annoying, as RSSOwl minimises to the tray but hides its icon when you reopen it triggering this bug. And some quirk of how the icons have ended up in the tray means it's often the icon for Semagic that vanishes from my taskbar.

Anyway, the workaround is to not use the NIS_HIDDEN flag but instead just add/delete the icon. Or if there's just one application causing it then I think moving it to the bottom-right corner of the tray also solves this, as stuff in the last row seems to be reordered correctly.

I wonder how one goes about reporting bugs to Microsoft?
torkell: (Default)
I'd forgotten just how primitive the string parsing in C is.

Semagic bugfixing: XMPlay music detection )
torkell: (Default)
So I've been trying off and on for a week now to get Semagic to compile, because I want to try and fix a couple of minor annoyances in it and official development seems to have stalled. Unfortunately the build process doesn't appear to be documented, nor are the required dependencies, and it's turning into a game of throwing random dependencies together in the hope that it compiles. For added fun the source tarball contains project files for Visual C++ 6, Visual C++ 2003 and Visual C++ 2005... but it's not clear which one is actually used.

This was surprisingly successful )
torkell: (Default)
Anyway, enough ranting about nutters on the road. Remember the file uploader I hacked together earlier this year? Well, I discovered a slight flaw when using it with the Wii U - the filename provided by the console is static, and so later uploads overwrite earlier ones. That's easily fixed...

PHP! )

The change is only a few lines - the call to move_uploaded_file has been replaced with

      $pathinfo = pathinfo($_FILES['file']['name'][$i]);
      $dest = $pathinfo['filename'] . strftime('-%Y%m%d-%H%M%S.') . $pathinfo['extension'];
      move_uploaded_file($_FILES['file']['tmp_name'][$i], $dest);


The result is each uploaded file has the current date and time appended to it (for example, vorpal.jpeg becomes vorpal-20141120-205045.jpeg). Obviously this will still overwrite files if you manage to upload the same filename multiple times within the same second, to which my answer is meh! As before, feel free to use it under the 3-clause BSD license.
torkell: (Default)

Eclipse is a maze of twisty build dependencies, all different. As best as I can tell there's the following:

  • Build path: this affects compiling and possibly running your project. Split into separate widgets for dependent projects and for libraries/jars.
  • Order and export: the same widget handles both the build order and "exporting" stuff to dependent projects, which may or may not actually achieve anything. Certainly the export option doesn't affect what appears in your .WAR.
  • Deployment assembly: this doesn't affect your build path, but instead controls what ends up in your .WAR should you generate one. This is also present in non-web projects and mostly works, except not all items are propagated to the web projects (e.g. if A is a web project and B and C are normal Java projects with a dependency A -> B -> C, the dependency from B to C isn't picked up by A. So A needs to explicitly require projects B and C even though it doesn't directly use C). Oh, and if you have a web project then I lied and any direct dependencies here are actually included in your build path.
  • Project references: the Java toolchain completely ignores this and makes no attempt to keep it synchronised with the other dependencies. Which is a shame, as the Eclipse interface uses this to work out which projects depend on other projects.

It all seems massively overcomplicated when what's really needed is a way to list libraries/projects and mark them as either "build-time", "run-time", or both. Then when compiling it uses just the items listed as build-time, and when running or creating .WARs it uses everything listed as run-time and includes transitive run-time dependencies as well.

torkell: (Default)

Okay, so it turns out that [livejournal.com profile] talismancer's post yesterday was filler. The moral balance has swung back!

As tempting as it is to fulfill the entirety of NaBloPoMo with us commenting on each other's posts, I feel like I should actually write something. So in the interests of increasing audience participation, I shall set a Java puzzler.

The puzzler consists of the following class:

import java.util.ArrayList;

public class Foo {
    private ArrayList<Object> barList = new ArrayList<Object>();

    public void fillBarList() {
        for (int i = 0; i < 10; i++) {
            Object o = new Object();
            System.out.println("Adding " + o + " at index " + i);
            barList.add(o);
        }
    }

    public void emptyBarList() {
        for (Object o : barList) {
            System.out.println("Removing " + o);
            barList.remove(o);
        }
    }

    public static void main(String[] args) {
        Foo f = new Foo();
        f.fillBarList();
        f.emptyBarList();
    }
}

Without running it (because that would be cheating and you will be mocked for it), what do you think will happen when Foo.main() is called?

torkell: (Default)

So, after 2 hours of writing some truely horrid Java code, I now have some shiny new comment stats from my shiny new LJ Stat-o-matic!


Top commenters on [livejournal.com profile] boggyb's LiveJournal
1[livejournal.com profile] boggyb484484
2[livejournal.com profile] olego162162
3[livejournal.com profile] pleaseremove100100
4[livejournal.com profile] ralesk6868
5[livejournal.com profile] pewterfish6464
6[livejournal.com profile] tau_iota_mu_c5555
7[livejournal.com profile] mirrordreams4242
8[livejournal.com profile] talismancer3838
9Anonymous3737
10[livejournal.com profile] dootsie3434
11-79 )

Total Commenters: 79
Total Comments: 1676
(not including 148 deleted and 3 screened)

Report generated Sun Nov 06 23:14:41 GMT 2011 by [livejournal.com profile] boggyb's LJ Stat-o-matic 1.0 (inspired by [livejournal.com profile] scrapdog's LJ Comment Wizard)


Credit where credit's due: [livejournal.com profile] scrapdog's original LJ Comment wizard is the inspiration for the tool and the result formatting, although I've ended up with a different calculation for the bars (his looks logarithmic, but I couldn't be bothered to do that and just made mine linear).

The other major difference with my stats is that I've excluded deleted and screened comments from the results. This has demoted Anonymous to #9 and restored [livejournal.com profile] olego to his rightful place at #2.

Source code is available if you want to run it yourself, but be warned - as said above, it was thrown together rather quickly over a couple of hours and doesn't contain a single comment!

torkell: (Default)
The Java HashMap class is not synchronised (and that is explicitly documented). This results in... interesting behaviour if two or more threads try to modify a HashMap at the same time.

Apparently, one of the failure modes is for the put() method to get stuck in an infinite loop.
torkell: (Default)

Something a colleague came up with at work the other day...

Consider the following Java classes:

public class FooBase {};

public class Foo extends FooBase {};

public class Bar {
  public Bar(FooBase) {
    System.out.println("Constructor Bar(FooBase) called");
  }

  public Bar(Foo f) {
    System.out.println("Constructor Bar(Foo) called");
  }
}

public class Test {
  public static void testSomething() {
    java.util.ArrayList<FooBase> list = new ArrayList<FooBase>();
    list.add(new Foo());
    FooBase item = list.get(0);
    Bar b = new Bar(item);
  }
}

Without compiling and running the program (because that would be too easy a way to solve this), what do you think will happen when you call Test.testSomething()?

My guess is that it will print "Constructor Bar(Foo) called", because while item is a reference of type FooBase the object being pointed to by item is actually of type Foo. But then the guy who came up with this pointed out that the output "Constructor Bar(FooBase) called" would also make sense, and if this were C++ that would be the expected output. The difference is all C++ knows is that it has a pointer to something that must be a FooBase, while Java knows that it has a pointer to something that is actually a Foo.

torkell: (Default)
Oh yes, and I almost forgot my recommended daily software rant: in Java, all bytes are signed. There is no such thing as an unsigned byte.

A side-effect of this is that a statement such as byte foo = 0xAA; gives a compiler error.
torkell: (Default)
This set of commands, run in a fresh gdb instance and intended to set a conditional watchpoint, results in gdb segfaulting leaving an orphaned debuggee running:

(gdb) watch function::variable if function::variable == 0xff
(gdb) run


This set of commands, again in a fresh gdb instance, works:

(gdb) info address variable
(gdb) info address function::variable
(gdb) whatis variable
(gdb) whatis function::variable
(gdb) watch function::variable if function::variable == 0xff
(gdb) run


Discuss.

gdb fail

Sep. 11th, 2009 08:07 pm
torkell: (Default)
It never ceases to amaze me just how backward the Linux development environment is.

Today I attempted to debug a test program that segfaults about 5 minutes after startup for no apparent reason. I managed to get a core dump of it, and loaded it into gdb in the hope of finding what was going on. Hahaha.

gdb could give me a valid stack trace showing the error, and could disassemble the program around the error to show me the actual instructions involved. However, gdb could not tell me the value of all the variables there (it claimed that some variables weren't even defined, nevermind that the program uses them all over the place!), nor could it actually match the disassembly up to the source.

Come on, folks, Visual C++ has been able to do this for decades! The Windows debugging tools are so far ahead it's embarassing for Linux.

I did actually discover a patch to gdb to achieve this, submitted April last year. Unfortuantly it's not in the latest released version of gdb (released March last year), and I really don't fancy building gdb from source myself.
torkell: (Default)
At work today I was debugging a problem in a bit of code, where somewhere between two systems a string was being truncated. There's three units and multiple programs involved in this, so to try and narrow it down I decided to add some debug to one program. The particular system on that unit uses a flowchart-like execution structure, separating actual code from the flowchart diagram. So, add in a debug node to print out the string when one flowchart has grabbed it from the other, rebuild the chart and transfer it to the unit, run it and it's still truncating the string. But that debug node was rather unhelpful and only printed out the first few characters, so I still don't know where the truncation is occuring. Not to be defeated I dug out a better debug node from the depths of the source control, compiled it, transfered it to the unit and plonked it into the flowchart.

At which point it stops truncating the string and sends the full text all the way through the system. Ah-hah, I think, this must be a heisenbug (adding debugging code can have very subtle effects on program behaviour). I'll remove my debug node from the flowchart, rejoin the original pair of nodes together, and upload the chart.

And it's still working. Ok, I think, the act of converting the chart for the unit must have changed it slightly from the original. It shouldn't do so as that implies non-deterministic code somewhere, but that'd at least explain what's going on. So I dug out the original already-converted chart and transfer that, thinking that this'll now restore the broken behaviour (when debugging it's always helpful to be able to reproduce the original bug - if you can reliably reproduce it, you can use a debugger to see every step involved and often quickly spot the actual problem).

Except it's still working!
torkell: (Default)
My coding Muse has found me again, which is good. I've just spent the past few hours cranking out code for my LiveJournal journal reader, and bashing together a bit of hackery involving internet explorer, visual basic 6 and on-demand post loading. It's now almost at beta level. The only major bug remaining is that friends-only posts *still* don't work, and I think that it's LiveJournal's problem. See the previous post for details.

Now I just need to turn my fingers to the other programs I've been meaning for a while to code. That or actually release something - a trawl through my code folder showed about half-a-dozen programs at release quality, an ancient attempt at writing a Pokémon clone, various unfinished programs ranging from an empty file to a complete UI skeleton, and some stuff that I don't remember writing. Oh, and one program that I think I wrote, but am not actually sure. It has my style, but I can't remember ever writing it.

You know you've been programming too long when you can't remember why you wrote something.
torkell: (Default)

Of all the fun things to encounter with Visual Basic 6:

"Unexpected error occured in code generator or linker. --View error messages?" Yes/No/Help

*Yes*

Wide error message )

I didn't think it was possible to generate an internal compiler error in VB.


Edit: okay, I think I've worked out what line is killing it. Unfortuantly, this line of code basically reads "MyControl.Data = GiganticVariableSizeByteArray", and is a rather critical line for that control to work. I may have to abandon that idea of mine. The compiler appears to dislike moving large byte arrays around.

torkell: (Default)
VB is not designed for bit mangling. It goes to great lengths to make such things hard to do (no unsigned variables larger than a byte, and no bit shifts).

That's not stopping me attempting to decompress S3TC with it, or convert between big and little endian, or generally do horrible bit manipulation. All hail user-defined types, and the mighty LSet operator!

May 2025

S M T W T F S
    123
45678910
111213141516 17
18192021222324
25262728293031

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Aug. 6th, 2025 06:15 pm
Powered by Dreamwidth Studios