Skip to content

XE3 RTL Changes: A closer look at TStringHelper

For those adventurous types who like to get down and dirty spelunking in the RTL source, you have undoubtedly noticed that there have been quite a few changes made to the runtime code. If you aren’t the type to immediately diff the latest source code to the last release to see all the new "goodies", I’ll try to provide a quick highlight of some of the more significant changes you might find.

One of the most notable changes in the RTL is the addition of record helpers for simple types. Rodrigo Ruz did a nice job covering them in a recent blog post which you may want to read. There are several useful things that that record helpers provide:

  • Code completion when typing a dot after a variable name
  • Encapsulation of common operations that can be performed on the type
  • More conscience and intuitive naming for operations

TStringHelper is definitely the most significant of all the new record helpers. It’s also unique in that it offers another benefit in addition to the ones mentioned above: helping you to prepare for a brave new world that is coming.

If you look at the declaration of the helper in System.SysUtils.pas you’ll see that is has dozens of methods and properties. One of these, whose usefulness may not be immediately obvious, is the "Char" property. If you read the post from Rodrigo, you’ll know that like all of the other properties on the string helper, this one is zero based. This is going to be important when writing code which needs to work regardless of the current state of the compiler directive which controls zero based strings. This property, unlike the more common "string[index]" syntax, always reads into the string data starting with a zero based index. Here is a quick code snippet to demonstrate the difference:

Zero based string sample

Zero based string sample

As you can see the code using the Chars property doesn’t change whereas the "normal" string indexing does.

The XE3 RTL source code has been refactored to be string index base agnostic. In most cases this is done by utilizing string helper functions which are always zero based. When it is necessary to traverse a string, the Char[] property is often used to access the individual characters without concern for the current state of the compiler with respect to zero based strings. In addition, the "Low" and "High" standard functions can now be passed a string variable to provide further flexibility as needed. When zero based strings are enabled, Low(string) will return 0,  otherwise it will return 1. Likewise, High() returns a bounds adjusted length variation. One important "gotcha" to watch out for here is that you don’t want to use Low() and High() together with the Chars[] property since the values they return change and what Chars[] expects does not.

Hopefully, you’ve inferred from what I’ve covered so far that zero based strings are something new in the compiler. There really isn’t much more to say about them other than: they are either ON or OFF and they change how the compiler interprets the value inside the brackets that follow a string variable. In addition to the directive you see in the source example above, you can also control this using the –zero-based-strings[+|-] switch to the command line compiler. Obviously zero based strings are disabled by default in the current desktop compilers, but there is always the possibility that could change in some possible future.

I had hoped to cover a few more of the changes in this post but it’s already getting a bit long so I’ll be back soon with more.

Tagged ,

SafeMM Debug Memory Manager available on CodeCentral

In my CodeRage talk,  Debugging Techniques for Delphi, I gave a short demo of using 2 different debug heap managers to help track down memory issues.  In the demo, I showed FastMM and another memory manager called SafeMM.  FastMM has been around for a number of years, and I’m sure many of you have used it in the "fulldebug" mode to help find memory errors.  SafeMM, on the other hand, has only been available publicly since my CodeRage session.  The source files are available on CodeCentral.

SafeMM works by not immediately re-using freed blocks and using the page protection flags that are part of the operating system.  It does an excellent job of detecting reads and writes beyond the boundaries of a memory block as well as any access to freed memory.   FastMM can also detect these types of errors, but it doesn’t typically detect them right when they occur.

Because of the way it is designed, SafeMM will require significantly more memory than the normal memory manager and typically cannot be used for extended periods of time without causing "out of memory" errors.   For best results, try to use SafeMM to test a very specific set of steps for a failure.

If you have an elusive bug that you suspect may be related to heap corruption give SafeMM a try.  It works great.

Many thanks to Ben Taylor for giving permission to share this useful debugging tool with the Delphi / C++ Builder community!

P.S. If you want to see just the debug memory manager demo from the CodeRage talk you can fast forward to about the 23 minute mark.

Tagged

A visit with Delphi 1 (redux)

When last we met[1], I was reminiscing about my reunion with the very first release of Delphi.  I still get a thrill running "delphi.exe" and watching it just instantly appear.

Of course time marches on, and today I’m sad to report that my old pal no longer runs on my current Windows 7 x64 development platform. 

But that’s OK, because with a few registry tweaks and a couple of command line switches, I’ve now got the new Delphi 2010 popping onscreen and running those same little apps and he’s every bit as snappy as his 16 bit ancestor.

Here is a quick little video of Delphi 1 running the "Hello World" app and Delphi 2010 doing a fantastic impersonation:

Delphi 1 Demo

Delphi 1 Demo

While writing this post, I was listening to the 10th anniversary interview with Anders Hjelsberg and Gary Whizin talking about the creation of Delphi.  Great stuff, and check out the launch demos and scripts from Anders while you are at it.  The DBBROWSE.DPR project still runs and works with no changes in Delphi 2010!

I definitely feel very honored to have the opportunity to work on a product with a legacy like Delphi.  In an industry whose only constant seems to be rapidly changing technology, it’s a very rare privilege to get to work with a product that has enjoyed such a rich, long life.  I’m especially grateful for the loyal user base who has kept us going for all these years.  Delphi is a great product, but it would be nothing without the fantastic community that has sprung up around it.

The launch of Delphi 1 was a exceptionally fun, once in a lifetime, experience — I wouldn’t trade those memories for anything –but I do believe that the best is still yet to come for Delphi!  Thanks everyone for being a part of it.

And for your parting gift, and reading this far down, here’s a picture of the back of the original Delphi 1 Client/Server box…

Delphi Client/Server Product Box Back

Delphi Client/Server Product Box Back

[1] Yeah, yeah, I know it’s been awhile, but really, the rumors of my demise have been greatly exaggerated. I’ve found my blogging quill in the back of the my desk drawer so I promise not wait quite so long before my next blog post.

Tagged ,

A visit with Delphi 1

I stopped by for a visit with an old friend today.  My long lost pal Delphi 1.

You remember him, right?  Lightning fast hand optimized 16 bit assembly language Pascal compiler, wrapped in a slick little GUI IDE, that enabled even neophyte developers to effortlessly build COMPILED stand alone executables for Windows in just minutes.  Yeah, that’s the guy.

Boy the memories came flooding back.  I just typed "Delphi" and poof, he instantly appeared ready and waiting to do my bidding.  So I dropped down a button, gave a couple of quick clicks and tapped out "Caption := ‘Hello World’;".  Next I reached up and instinctively pressed F9 just like I’ve done so many, many times over these last 18+ years.

That’s when it hit me and I remembered why we were such fast friends. To say that running the application was instantaneous is an understatement.  It’s more like turning on a light switch.  There was quite literally NO PERCEPTIBLE DELAY going from design to run mode.

So I just sat there like a kid who has discovered the light switch for the first time.  F9,  Alt-F4,  F9, Alt-F4, F9, Alt-F4, wow…., F9, Alt-F4, F9, Alt-F4, F9, Alt-F4, unbelievable…, F9, Alt-F4, F9, Alt-F4, "hey Steve, you gotta come check this out…", F9, Alt-F4, F9, Alt-F4…

Anyway, it was a great visit, and I promised not wait so long before the next one.  In fact, I think I’m gonna invite him over to meet this new guy around here we call "Highlander" and teach him some of those really cool performance tricks…

Using AQTime as a Delphi Debugging Tool

Background

Here’s the dilemma: You’ve got some code in front of you that you know basically nothing about and it doesn’t work. Well, actually, there’s just one little part of it that doesn’t work, but the trouble is you have absolutely no idea where or what that little part is. Your job is to fix it. Where do you start?

I recently ran into this problem when trying to debug a drag and drop problem in Delphi 2006. I hadn’t debugged drag and drop code, and I’m sure anyone who has appreciates the challenges of using the debugger to figure out what is going on during a drag operation. The big problem is that if you want to set a breakpoint in the code which executes when the drag operation begins, you won’t be able step though all of the code that needs to execute to complete a drop operation because the mouse messages will not be processed properly by the application while it is stopped in the debugger. As soon as the breakpoint hits, your drag operation is basically cancelled.

The bug I was working on had to do with being unable to rearrange items in the tool palette using the mouse. On certain systems, the tool palette would simply not allow dragged items to be dropped.

In this situation, the Delphi IDE uses "OLE" drag and drop which means much of the code that executes during a drag operation is invoked by callbacks from the operating system. Since this callback is called indirectly, it is more difficult to identify. It’s awfully tough to set a breakpoint on a line of code when you don’t know where it is! The problem was further complicated by the fact that code that should have been executing wasn’t getting called, so even if I knew where to put the breakpoint it wouldn’t have worked.

I decided to use AQTime to tackle this problem. Not only is it a powerful code profiler, it is also a very useful debugging tool. The results it generates will show which functions are called, how many times they’re called, and how long each call takes. In addition, it provides a call stack that clearly shows which functions call other functions. Another nice thing about the call stack AQTime provides is it’s "static" nature, you don’t have to be sitting on a breakpoint with the program running to review it as you normally would with a debugger.

The Debugging Process

To get started, I found a system that was not affected by the bug and profiled the drag and drop operation. This gave me a "good" set of profiler data. I copied the results to a system that couldn’t perform the drag and drop. Now, using the same AQTime project with the good results, I executed the same steps (which failed) under the profiler. This gave me a "bad" set of profiler data. Next, I used a feature in AQTime which allows you to compare these two sets of results. That allowed me to quickly see which methods were not being called on the computer affected by the bug. Finally, I analyzed the call stacks from each profiler run to determine where the execution paths diverged.

At this point, I had the information I needed to jump back into the debugger and set some breakpoints and figure out exactly what was going wrong. This took me just a couple of minutes, now that I had a clear picture of what the expected code path was. From there I made a few code changes to fix the bug and: Viola!, problem solved1. I’m sure there were probably other ways I could have attacked this bug, and had I gone into this exercise with more background in drag and drop code I probably would have known right where to look for the problem without any extra help. Fortunately, having AQTime in my toolbox I knew I could get the job done with this approach.

Final Thoughts

It’s incredibly useful to have a "static" call stack that you can examine after the fact. You can walk up and down the stack and review the associated code in the code editor window and review any part of the profiler results without having to run the program. Another big advantage of the call stack AQTime provides is that it traverses the .net managed/unmanaged code interop boundary showing you a full picture of the code execution. The IDE debugger only allows you to see either .net or Win32 calls in the call stack, not both.

1 In case you are curious, the bug involved the use of the IDragTargetHelper. The DragEnter method returns an error code when the "Show window contents while dragging" option is disabled in the operating system. The workaround for the bug is to enable this option in the OS.

Delphi Startup Times and The Kitchen Sink

2005 wasn’t much of a blog year for me (boy is THAT an understatement!). Anyway, it’s a new year and I’ve decided to try and start over and begin blogging again. I’ve got quite a number of things I want to write about so hopefully I’ll find the time to crank out at least a few entries each month. No promises on that but I’m planning to give it a shot at least. To kick things off, I’ve written up an article that describes a new Delphi command line switch that is used to configure the IDE to startup with a single personality. This new switch, -p, will be quite handy if you want tailor the default configuration for the kind of development work you do. You will need to be prepared to roll up your sleeves and do some spelunking in the system registry, but that should be nothing for anyone smart enough to be using Delphi for development, right? The article is a little long for a blog post so I’ve published it here: Delphi Startup Times and The Kitchen Sink I hope you find this useful. Happy New Year! Mark

Update May 5th 2009: Link to missing document fixed.

Bloglines (Keep New)

Yikes!  My last post was August 3rd!  My only excuse is that there is a certain product we have been working on around here that has been chewing up a “little bit“ of my time.  I actually haven’t been finding the time to READ blogs, let alone write them.  Anyway, now that things are winding down around here I’m starting to catch up on things I’ve been putting off.

I’m really impressed with the Bloglines news aggregator, it works very well for my blog reading style and I think I will write a series of entries to go over what I think are some of it’s strong points.  If you haven’t checked it out I highly encourage you to take it for a spin.  If you are already addicted to another news reader I think you will find Bloglines to be very complementary.

Keep New

At the moment, I’m reading through 513 blog entries on the Scobleizer blog going all the way back to August 1st (where does that guy find the time!).  Obviously, I’m not going to be able to read them all carefully or follow the links, but there are at least a few I want to look at more carefully.  If you have used Bloglines for awhile, you will know that has not always given you the ability to mark only certain blog entries as “read“.  It used to be that just selecting a particular feed would automatically mark all of the items in it as read and if you really didn’t want them to be marked as read you would have to use this “session“ option to go back in time.   It was really awkward and if you accidentally selected a feed that you didn’t want to read or had too much content for you to read at one sitting.  It just didn’t work very well.

Fortunately, while I was on hiatus from the Blogshpere, the folks at Bloglines came up with a solution to that problem which works very nicely I think.  They have added a little “Keep New” checkbox to each blog entry.  When you select it, that entry will show up the next time you return to read a particular feed along with what ever new content may have appeared.  

Depending on what your blog reading habits are like you might hate this or love it.  Unlike reading my email, there are far more blog entries on a given feed that I am NOT interested in reading than there ones I am interested in.  So the whole concept of marking everything as “read” with a single click works better for me in this case.  I’m about half way through those 513 entries I mentioned earlier and so far I’ve marked 12 items to keep as new.  Tomorrow, or the next day, (or next year <g>) when I come back to the same feed those items will be in the list again for me to revisit.  This of course is completely opposite of what I would want for my email.  I couldn’t have all my messages getting marked as read just by selecting my Inbox folder!  In that case, selecting the individual message to read make more sense.

I’ve used a couple of other aggregators that work the way Outlook and most other email readers work, where things get marked as read one by one as you select them and I found that just doesn’t work for me with blogs.  I really like having all 513 blog entries show up at once and being able to very quickly scroll through them without any refreshing or reloading needing to occur.  It’s even possible to have each entry collapsed by default for the those feeds where there is REALLY alot of content (like http://weblog.asp.net)

My “wish list” suggestion for the Bloglines folks would be to add some way to mark a group of entries (but not all) for “Keep New”.  Unfortunately, this isn’t going to be easy to pull off given the limitations of the browser based UI.

I’m excited to see this product evolving and improving!

Delphi 7.1 Update - Database supplemental now available

An update has been posted to Code Central which addresses several bugs that were introduced in the original Delphi 7.1 update.  You can find the details here:

http://bdn.borland.com/article/0,1410,32492,00.html

Special thanks goes to Dave Rowntree (Quality Central sysop for Midas/Datasnap) for his help in identifying the issues and being patient while folks around here coordinated the release of this update.  Folks around here are working pretty hard on upcoming products, so it took a little longer than I would have liked to get this out there, but we pulled it off.

XML Data Binding Wizard Fixes

I’ve just uploaded an update to Code Central which fixes a couple of problems you may run into if you are using moderately complex XML schema documents with the XML Data Binding Wizard.

Relative paths were not being handled correctly for “includes“ and there was also a problem with resolving types.

Thanks to Dave Brown and Gary Conley for bringing these issues to my attention on the borland.public.delphi.xml newsgroup.

Update: June 6th 2005 - Updated the link to the download on code central, please post a comment if you have any more problems with it.

Blame the bad UI

It seems my first post didn’t actually get syndicated.  I really should have caught this myself but when I went add my own feed to my bloglines account I thought “that seems a little weird doesn’t it, why would I want to read my own feed?“ and so I didn’t do it.  Now I know there is a good reason to do it: To make sure it’s working!. Especially when you are dealing with a blogging tool that leaves the door wide open for error.  Take a look at this screenshot from a part of the entry screen for creating and editing posts in the .text blogging client:

Notice where the checkboxes are on top relative to what they are for.  Now look at where there are in the “Advanced Options” section.  They are on the opposite side!  How whacked is that?  Checkboxes that appear to the right of the text they represent are counter-intuitive enough by themselves, but when you start mixing them with checkboxes on the left, that’s just plain bad.

Anyway, if you haven’t figured it out by now, the reason my first post wasn’t syndicated is that I hadn’t checked the right checkbox.

Thanks to Nick Hodges for pointing that out to me on his blog.

Bad Behavior has blocked 87 access attempts in the last 7 days.

Close