Living with Repetitive Strain Injury (RSI)

By , June 5, 2021 2:08 pm

This article was written by myself in 2000/2001 and was originally hosted on a different website that no longer exists.

I have updated this with some extra information and fixed many typos.

I no longer suffer the physical health or mental health problems described below. I am re-posting this article in response to a discussion with someone on twitter who is in the early stages of suffering with RSI. I hope that by posting this RSI related article people will read it, understand there is a way out of this problem if they take the correct action.

Your health is the single most important thing you have.

Without health everything else in your life suffers. Health is more important than wealth.

Background

My history with RSI goes back to 1988, culminating in being so ill in 1993/1994 that I had to take 3 months off work, and spend the next 3 months working slowly with the aid of voice recognition. During this time I had to do remedial exercises 3 or 4 times a day, lasting between 20 and 40 minutes each session, and go for a 2 hour walk each day. This exercise regime was intended to improve my posture, range of movement and muscle strength.

Since returning to work, I have been able to reduce the amount of exercises by taking vitamin B6 supplements (Vitamin B6 helps tendon sheath healing) and swimming at least every other day, and preferably every day. I have found that for my level of health, I can swim 750m (30 lengths of average 25m pool) without incurring further injury, but that if I swim beyond length 850m (length 34) I often do more damage to my arms than the benefit I gain. It has taken me 8 years to regain this level of fitness.

Whilst ill I have experienced feelings of helplessness and depression because of this helpless feeling. I have had pains I can’t describe to other people (because RSI doesn’t feel like other pains). I have had to put up with people accusing me of being a malingerer, a work shy person. I have had this accusation even when I worked for myself. Just because I look healthy, doesn’t mean I am. I have at times had very cold hands, and once for a period of 2 weeks I had two blue hands. This was very painful.

I’ve explained this background in brief so that when you read this information you realise that I have very real and painful experience of how debilitating RSI can be. Having established this fact, hopefully you will place some credence on the advice given here. I’m not trying to claim that I’ve had worse RSI than someone else. Its not a competition :-). I have had a bad time, and I have come out the other side and kept my career. Mainly because I pay strict attention to my exercise regime, and when in too much pain I abandon all activities that are not essential, in order that I can recover my health and remain able to work. Against that playing a mandolin or bagpipe doesn’t count for much, however much fun. I stress this because if someone can be as ill as I was and still keep their career, the odds are that the same result can happen for you.

WRULD

RSI is known as WRULD (Work Related Upper Limb Disorder) in the USA. This name is misleading. RSI can affect all parts of the body, and is not necessarily caused by solely by your work. It is most likely caused by an interaction between your work activities and your non-work activities. For example double-hand use when a software engineer goes home then plays their musical instrument in the evening. Calling the injury WRULD is overly specific and focuses on the wrong things. RSI is a far better descriptor because it describes what is happening without making any claims about which part of they, or which activities are responsible for the problem.

Types of RSI that may affect you as a software engineer

Typical RSI related arm/hand injuries are epicondylitis, bursitis, tenosynovitis, tendonitis and carpal tunnel syndrome.

Epicondylitis

Bursitis

Tenosynovitis

Tendonitis

Carpal tunnel syndrome

Cortisone

Try not to let anyone inject you with cortisone. You can only have this 3 times in your life (it is not good for your bones).

Also this is treating the symptoms, not the cause.

Its a painful injection, I’m told, but does provide short term relief.

Carpal tunnel surgery

Carpal tunnel surgery. I’d advise against it, if you can get proper medical treatment you won’t need it. I’ve heard some nightmare stories about it taking up to 6 months for the operation to heal. However I met a doctor last year, and she had had both her wrists done for this operation and was back at work a few weeks later. I guess there is a lot of variance with this operation.

It won’t happen to me

Do seek advice. Don’t think “I’ll live with it, it won’t happen to me”. Everyone thinks that and they always realise they were wrong, when it is too late.

Ergonomics

Your environment should be changed to suit you, not you change to suit the environment. The classic mistake that most people (myself included) make is to get to a workplace, adjust the chair height to suit the desk height and their own height. This is the wrong way around!

The body you have is the one you have to live your life in. You can’t realistically change your height, the length of your torso, the length of your legs and the width of your hips etc. Given that these are not available for modification, we must turn to your work environment.

Lets face it you spend 8 or more hours a day at work. Thats a 3rd of your life you spend there, so you’ll want it to help you and not damage you. If you have a good employer, they will also appreciate that its in their interest to keep you happy and healthy, as happy and healthy employees tend be more efficient, make less mistakes, take less days sick and be more likely to stick around rather than look for a new employer.

So how do we do this? First off we start with how you sit, and what you sit on, not the desk you sit at (we’ll come to that later).

Chair


  • You should have a chair with a five (or more) castor base.

  • The chair should be able to rotate

  • The chair seat should be adjustable in height.

  • If possible the chair seat should tilt forwards and backwards.

  • The chair back should be the length of your back and fully support your shoulders.

  • The chair back should be adjustable vertically.

  • The chair should have independently adjustable arms.

How should the chair be adjusted?


  • When sitting the chair, the chair height should be such that with your feet flat on the floor, you can sit in the chair comfortably.

  • The chair seat should be tilted slightly so that the front of the seat is slightly lower than the back of the seat. This causes your pelvis to tilt and improve the ‘S’ shape of your spine to provide more support to your body. This also causes your shoulder and head to be balanced better.

  • The chair seat depth should be chosen (on good chairs you can do this when you buy it) so that when sitting on the chair, you can get your hand (about 3 or 4 inches) between the back of your knee and the seat edge. If the chair is too deep you’ll never be comfortable. If the chair is too shallow you won’t get enough support.

  • Adjust the chair back to support both the lower back and your shoulders. This should not be a problem if the correct length back was purchased with the chair.

  • The angle of the chair back should be quite upright and not laid back. A degree of personal preference comes in here, but basically the more upright it is, the better your posture will be, the more laid back it is, the worse your posture will be and the resulting likelihood of RSI increases.

Good chairs don’t have to cost a lot. With government legislation and the increasing likelihood of RSI lawsuits, good quality chairs that offer most, if not all of the features described are now available at good prices. You don’t have to spend £600 or more, but you can. Don’t assume that more cost equals better chair. This is not always the case. My own chair cost £300 in 1994. The nearest thing I can find to it now is about £1000. I view it as money well spent, as other chairs I have sat in have caused me no end of posture problems and pain.

Sadly, many organisations use furniture as a means of stating authority. Which usually translates into the people doing the software having a poor quality chair, often with no arms. Senior staff get chairs with arms (they are valued so much!), and managers get decent chairs. This is an archaic way to view the workplace. Why these organisations don’t value their prize assets (their staff) more highly I do not understand.

The organisations I have seen do this, always lose the good staff. They realise what their employer thinks of them and leave because they know their own strengths and abilities. I digress, but if you are an employer and you are reading this, think about it, then go out and buy some great chairs for your staff.

What should I buy?

I don’t recommend heading down to your local Best Buy or IKEA, or buying chairs from the printer paper company’s catalogue. They do sell “office chairs” but they aren’t what I’d sit on, and I wouldn’t expect you to sit on them if you were working for me. Your body is the most valuable thing you own, and you probably didn’t go cheap when you purchased your workstation/laptop, so why would you do that when looking after the most valuable thing you own?

I can’t recommend the people that sold me my superb chair, as they are sadly no longer in business, but Posturite comes close to their ethos and design expertise. This isn’t a recommendation to buy from them, but an indicator of what you should be looking for. If they take your body measurements and then offer you chairs based on your dimensions that’s what I’d go with. Even better if they build chairs for you based on your dimensions (that’s how I got the chair I have – they wouldn’t sell me the chair without me completing a form so they knew my body dimension).

Also, don’t assume more expensive is better. I would never buy an Aeron. So much wrong with that chair design – it fails many of the criteria listed above.

Desk

Now that we’ve got the chair set up to suit your height and dimensions, we need to set up your desk. This is simpler than the chair.


  1. Sit at your desk with the chair adjusted correctly for your height. With your arms by your side, bend your arms at the elbow so that your lower arms are horizontal. Where your hands are is where the keyboard or textbook should be. That means the desk should be at a suitable height to allow this.

  2. If the desk is too low, then get some bricks and prop the desk up, or hire a carpenter to make some wooden supports to put under the desk.

  3. If the desk is too high, then you can either shorten the desk legs, purchase a new desk, or raise your chair seat height and get a foot support. If you do choose to raise the seat height (in my opinion the worst solution), you must get appropriate foot support.

Keyboard

Get an ergonomic keyboard (that doesn’t mean a ‘happy hacking’ style keyboard). The Microsoft natural keyboard is good (although the modern ones have a stupid cursor key layout). Other vendors also supply split keyboards. Some vendors (Maltron etc) supply completely different layout keyboards that are apparently very good. These are very expensive as not many are sold per year. I have one, but you need to use these all the time without returning back to QWERTY keyboards. As I have too many computers, I haven’t managed to do this.

Sitting at your newly adjusted desk on your shiny new chair, we can see how your keyboard should be set up.


  1. Roll your sleeves up so that you can see your forearm and wrists.

  2. Place your hands on your keyboard in the ‘home’ position (where your hands naturally go).

  3. Looking at your arms and hands from above (i.e. looking at the back of your hands), you arm and hand should be in line, with no bend at the wrist. You will find this much easier to acheive with a split or egonomic keyboard.

  4. Looking at each arm in turn, examine your arm and hand position from the side. Your hand should be level with your arm, and should not bend down or bend up at the wrist. If your wrist is bent his maybe caused by the chair/desk combination not being correctly adjusted, or because you have learnt to type like this.

Mouse

Find a mouse you like, or try a trackball. Some people get on with trackballs very well. I am right handed but use a mouse in my left hand. Experiment, try new options. Trackpads (such as on Dell notebooks) are useful. Experiment with using more than one pointing device (a mouse and a trackpad, or a trackpad and trackball) so that you can vary your hand use.

Monitor

With your chair and desk adjusted, we can adjust your monitor position appropriately. Sitting in your chair, the top of the visible portion of the monitor image should be roughly at eye level. Taking a 10′ or 11′ degree angle downwards from your eye position to the monitor should bring you to the bottom of the visible portion of the monitor image. Move the monitor further away from you or closer to you until this is acheived.

You may need to prop the monitor up on blocks to get the monitor the appropriate height. I have used (at different times) shoe boxes, redundant loud speakers and bricks for this task. You can also purchase hydraulic arms to move the monitor to a height suitable for you.

Employment

If your employer will not provide you with a chair, desk, monitor and keyboard that provides you (*) support, then I would think long and hard about what that says about their committment to you, your health and your future career prospects with them. Or, put another way, find a different and better employer.

(*) I mean you, not the others you work with – you are an individual, whats good for them isn’t necessarily good for you.

Treatment

The exercises given here are based on the exercises given to me by my physiotherapist. The basis for these exercises is a treatment known as Adverse Mechnical Tension.

All stretches must be held for a minimum of seven real seconds, preferrably ten seconds. The reason I state real is because I mean 7 seconds on a clock, not seven seconds the way people count out loud (too fast). The reason the stretches must be held for this length is that the stretches are stretching nerve tissue. Nerve tissue is elastic and doesn’t actually stretch (without springing back into its original size) until it has been stretched for 7 seconds. So if you do these exercises and don’t stretch for at least 7 seconds, you are wasting your time and doing yourself no good. Please re-read the previous sentence.

Disclaimer

These exercises are the exercises that I used to help recover from RSI as part of a treatment regime. I am not a trained physician or medical practioner, so any advice here is my description of the exercises given to me by my physiotherapist. You use these exercises at your own risk. If in any doubt about the validity of these exercises with respect to your physical health, consult a trained physician, physiotherapist or other appropriate medical authority.

If any exercise causes you pain, stop doing the exercise immediately. Try a different exercise.

Exercises

The exercises given here are intended to help you regain your range of movement and improve your posture. The exercises should not cause you any more pain than you are presently experiencing with your RSI. If any exercise does cause you pain, stop doing that exercise and move on to a different exercise. As your health improves you can revisit any exercises that you had to skip.

The exercises can be done in any order, although you may find that you have a preferred order to do the exercises in. I tend to do all standing exercises, followed by all sitting exercises, followed by all floor exercises.

Good times to exercise are in the morning before you start work, in the evening after work, and before you go to sleep. Additionally you may find doing these exercises at work in your lunch break helpful. Work colleagues may find it unusual to see someone doing these exercises. Dont let that put you off. If you can find somewhere private to exercise that is usually better.

Whilst doing the standing exercises, emphasis is to be put on standing correctly, shoulders back (where they should be) and no slouching. However, don’t lock your knees, don’t stand on tip toes, or with flat feet (ankle collapsed inward). Your feet should be flat on ground, at shoulder width.

You will notice that most of these exercises do not work directly on your hands or arms. That is correct and intended. Your body is a complex machine, with levers (bones) and pulleys (tendons). These exercises are designed to increase range of movement and to also increase muscle strength. The lying down exercises increase the strength of your stomach muscles.

In an ideal world I’d have images and video clips to demonstrate how to do these exercises. I was persuaded to put this article together after chatting with Christian Graus (WDJ Author) about my experience with RSI. I haven’t had time to get any photos scanned or videos made. I will produce these in due course and put them here with the appropriate exercise.

Touch the ceiling

Stand up straight, with your arms at your side. Do not slouch. If in doubt look in a mirror and make sure you are not slouching. Whilst breathing in, raise your hands from your sides to above your head as if trying to touch the ceiling. When you are doing this, your aims should raise to your sides, not in front of you. When your arms are above you pointing at the ceiling, you should stretch your arms to the ceiling. Do not stretch your hands. The stretch should end at your wrists. Wait for 7 seconds, and lower your arms (reverse of previous raise, your arms should not go in front of you) whilst breathing out.

Its important to breath in and hold your breath whilst stretching as this improves the stretch. Make sure you can stretch and have your arms straight. If the ceiling is too low and you can’t do this, find a different room or go outside.

Repeat this exercise 10 times with a short break between each stretch.

Touch your toes

Whilst doing this exercise, be sure to use your stomach muscles to support yourself as you bend, otherwise too much strain will be placed on your back and you may hurt yourself.

Stand up straight, with your arms at your side. Do not slouch. If in doubt look in a mirror and make sure you are not slouching. Lift your hands above your head, arms pointing straight up. Now start to bend over until you can bend as far as you can, attempting to touch your toes. Do not force it. Wait for 7 seconds and straighten up.

Repeat this exercise 10 times. Each time you do this you should be able to stretch further. Do not bend your legs.

Windmill

Stand up straight, with your arms at your side. Do not slouch. If in doubt look in a mirror and make sure you are not slouching. With your arms straight, swing one arm forwards clockwise, and the other arm backwards. After a few rotations, reverse direction. Your arms should be 180′ out of phase.

Forward stretch

Stand up straight, with your arms at your side. Do not slouch. If in doubt look in a mirror and make sure you are not slouching. Clasp both hands together, interlocking your fingers. Place your hands in front of your chest and stretch your arms forward until you can stretch no further whilst your hands are clasped together. Hold the stretch for 10 seconds.

Repeat this exercise 10 times.

A variation is to turn your hands ‘inside out’ when at full stretch so that your wrists are one the outside of the stretch. Do not do this if it is painful.

Sit and twist

Find a typical table chair – i.e. one that is not on castors. Sitting upright on the chair (do not slouch), wrap your arms across your chest so that you have your right hand on your left shoulder and your left hand on your right shoulder. This is to get your arms out of the way. You are sitting down so that the next exercise does not twist you hips, but does twist your spine for the full length of your back.

Now turn to the left, turning as far as you can with your body and your head. Your legs should remain facing forward. By turning left, you are trying to look right around yourself so that you can see objects on your right handside. Turn as far as you can. Hold this for 10 seconds. Now repeat this exercise by turning to the right as far as you can, trying to see around yourself so that you can see objects on your left hand side. Hold this for 10 seconds.

Repeat these two twists. Repeat these two twists, for a total of 3 twists each way.

Typically after doing this exercise you will find that the touch the ceiling and touch your toes exercises are easier to do.

Sit and stretch

Find a typical table chair – i.e. one that is not on castors. Sitting upright on the chair (do not slouch). Lean forwards over your knees and try to touch the floor in front of your feet. Stretch as far as you can. Hold this for 10 seconds. Return to the sitting position.

Whilst doing this exercise you may get an unusual sensation (but not pain) in the base of your back as the stretch starts to work. My experience of this is that it means the stretch is working.

Repeat this exercise 3 times.

Typically after doing this exercise you will find that the touch the ceiling and touch your toes exercises are easier to do.

Punches and shoulder rolls

Stand up straight, with your arms at your side. Do not slouch. If in doubt look in a mirror and make sure you are not slouching.

A shoulder roll is where you roll your shoulder up, back, down, and forward to its original position. Shoulder rolls can be done either one shoulder at a time or both shoulders together. I was taught to do shoulder rolls one shoulder at a time, but have found then to be more effective if I do both together.

The exercise is to do ten shoulders rolls, then ten rolling punches, one with each arm, alternately.

Repeat this exercise 10 times. Then finish with another 10 shoulder rolls.

It is important to always start with shoulder rolls and always finish with shoulder rolls. This is because rolling punches pull the shoulder forward, and shoulder rolls pull the shoulder back. We want the shoulder position to be back. People with poor posture often have shoulders that are very far forward of where they should be. This exercise is designed to help put your shoulders back where they should be.

Finally, shoulder rolls also open up your sternum, which on many people is very inflexible, but which should be more flexible.

Prayer and twist

Stand up straight, with your arms at your side. Do not slouch. If in doubt look in a mirror and make sure you are not slouching. Place the palms of each hand together, with your finger tips touching, fingers pointing upwards (thumbs towards your body, little fingers away from your body). Your hands should be in front of your face. This will look similar to a Christian prayer position. Slowly lower your hands (whilst keeping them pressed together and in the prayer position) so that they are half way down your body. At this point your lower arms should be horizontal (or as close as you can get) and your hands should still be pressed together. If there is any pain or tightness, stop at that point. Some people can do this with their arms horizontal, others cannot.

At this point there is another optional part of this exercise. When your reach the point where your lower arms are horizontal, you can rotate your hands away from you body whilst keeping them pressed together. Some people can only rotate their hands a small distance, whilst others can rotate their hands so that they are almost pointing down. Hold this position for 7 seconds, then rotate your hands back to the upright position.

Repeat the whole exercise 3 times.

Lie on floor, lift legs

Lie on the floor, lying on your back with your hands at your side and your legs straight. Slowly lift your left foot about 10 centimetres off the ground. Hold this position for tens seconds, then lower your foot to the ground. Repeat this exercise with your right leg.

Repeat the whole exercise 3 times.

Sit ups

Lie on the floor, lying on your back. Now raise you head and body and try to touch your feet. Repeat three times. Be careful not to strain yourself whilst doing this exercise.

Repeat three times.

Press up that isn’t a press up

Lie on the floor, face down with your hands under your shoulders and your elbows by your sides, as if you were about to a press-up. Slowly raise your body until your arms are straight, whilst trying to keep your hips touching the floor. When your are unfit, your back will be stiff and you won’t be able to do this (your hips will lift off the floor). As you get fitter you will be able to do this (my father, at age 62 can do this, so I’m sure you can too!). Hold this position for 10 seconds. Now lower yourself to the starting position.

Repeat this exercise 3 times.

Why does GetProcAddress() sometimes return an address outside of the DLL?

By , April 14, 2021 5:43 pm

For most uses of GetProcAddress() the address returned will be an address inside the DLL that you’re using to lookup the function.

But sometimes the address returned is not in the DLL. That’s odd! Is this a bug?

It’s not a bug. This intended behaviour. This article explains why it happens.

Before we get into what’s going on, let’s recap what GetProcAddress() does.

What is GetProcAddress()?

GetProcAddress() is a function exported from kernel32.dll.

It’s used for looking up the address of a function exported from a DLL.

The function can be exported by name (ASCII strings only) or by ordinal (an integer between 0 and 65535). Examples of DLLs that export by ordinal are the MFC dlls. Most DLLs export by name.

GetProcAddress() examines the export address table in the DLL looking for a function with the name (or ordinal) specified. If the function is found the address is returned, otherwise NULL is returned.

Here’s a demonstration looking up the address of the StarCrossedLovers(); function in the theatre.dll. This DLL handles all functionality related to the theatre plays needed by the application.

If the function is found it is called with the names of the two lovers, Romeo and Juliet.


HMODULE hModTheatre;

hModTheatre = GetModuleHandle(_T("theatre.dll")); // could be a call to LoadLibrary instead
if (hModTheatre != NULL)
{
    LOVERS_FUNC p;

    p = (LOVERS_FUNC)GetProcAddress(hModTheatre, "StarCrossedLovers");
    if (p != NULL)
        (*p)("Romeo", "Juliet");
}

Most of the time the returned address will be inside the DLL being queried.

Some of the time the returned address is not from the DLL being queried. Where did the address come from?

Where did the address come from?

When the address returned from GetProcAddress() is from outside of the DLL being queried, the address returned is an address inside another DLL that is supplying functions to the original DLL using a process called Forwarding.

To demonstrate this I’m going to examine the NetApiBufferAllocate() function which is exported from netapi32.dll.

If we call GetProcAddress() to look up the address of NetApiBufferAllocate the address returned on my Windows 10 machine is 0x70342800.

But if we look at the load address for netapi32.dll it’s 0x6fcc0000 and it’s size is only 76KB. The address returned is outside of netapi32.dll. If we then look at the other DLLs in the application and find which DLL contains address 0x70342800 we find it’s netutils.dll. Here’s a screenshot from VM Validator showing that.


OK, so we know the exported function address doesn’t come from the DLL we queried (netapi32.dll), but actually comes from netutils.dll. How does that work?

It’s going to be easier if I show two images of the netapi32.dll and netutils.dll while we examine the NetApiBufferAllocate() function.

These images are being viewed using PE File Browser. Both of these images show the DLLs loaded at their preferred load addresses (if you repeat this test with PE File Browser you’ll most likely get the same addresses).

netapi32.dll


netutils.dll


What you can see in the first image is that netapi32.dll has a NULL exported address for NetApiBufferAllocate and the the forwarding column shows NETUTILS.NetApiBufferAllocate. The forwarded function is composed of a DLL name, a period and the name of the exporting function (which doesn’t have to be the same as the original function name).

When you look at the exports for netutils.dll you can see that it exports a function NetApiBufferAllocate with non-NULL address.

What happens when you use GetProcAddress() to fetch the address of an exported function that has been forwarded from another DLL is that GetProcAddress() decodes the forwarded function name and looks up the forwarded function name in the forwarded function DLL. In the case of NetApiBufferAllocate in netapi32.dll that means GetProcAddress() returns the address of NetApiBufferAllocate in netutils.dll.

What’s the purpose of function forwarding?

I think it allows DLLs that were once large repositories for a variety of code to be split into many DLLs, each of which serve one purpose. These DLLs then forward the DLLs to the original DLL which is now acting as a central location (for backward compatibility) to find the functions. Client applications never know the code they are calling now resides in a DLL dedicated to the particular task rather than in the original monolithic DLL. This can be useful for the maintainers of the DLLs, improving maintenance, testing and security of the component DLLs.

If we return to the original example of the StarCrossedLovers() function exported from theatre.dll this could be reimplemented by moving all all Shakespeare related functionality out of theatre.dll into shakespeare.dll. StarCrossedLovers() in shakespeare.dll would then be forwarded to theatre.dll.

You could take it a stage further (sorry, no pun intended!) with each of Shakespeare’s plays being represented by their own DLL which forwards functions to shakespeare.dll (or theatre.dll).

What’s new with Thread Validator

By , December 10, 2020 6:27 pm

There are some changes coming to Thread Validator.

I’m going to describe the various changes and the reasons behind them.

Name Change

The first one is the name change. C++ Thread Validator becomes Thread Validator.

This change is to keep in line with our other tools not having language specific prefixes.

New UX Theme

A new UX theme which is has less visual clutter and is calmer to look at has been introduced. We’ve written about that in New UX Theme.


x64 and x86 support

C++ Thread Validator shipped in two versions, a 32 bit version and a 64 bit version that could also process 32 bit executables.

Thread Validator ships in a 64 bit version that can also process 32 bit executables. On a 32 bit machine the 32 bit version installs, on a 64 bit machine both 64 bit and 32 bit versions install, because occasionally there is a 32 bit native bug that you only deal with from the 32 bit version of the tool.

The reasons for this change are

  • All our other tools ship in versions that support both 64 bit and 32 bit executables. Thread Validator should do the same.
  • 64 processors are the dominant processors in the market. We should support these by default.

Availability

These changes to Thread Validator will be available after 13 December 2020.

What’s new with Performance Validator

By , December 10, 2020 6:26 pm

There are many changes coming to Performance Validator.

I’m going to describe the various changes and the reasons behind them.

Name Change

The first one is the name change. C++ Performance Validator becomes Performance Validator.

Because Performance Validator will be capable of handling multiple technologies and languages having language specific designators prefixing Performance Validator doesn’t make any sense.

New UX Theme

A new UX theme which is has less visual clutter and is calmer to look at has been introduced. We’ve written about that in New UX Theme.


.Net Support

Performance Validator now supports .Net languages. C#, VB.Net, C++.Net, etc.

.Net Performance Validator is discontinued, all of it’s functionality moving into Performance Validator.

x64 and x86 support

C++ Performance Validator shipped in two versions, a 32 bit version and a 64 bit version that could also process 32 bit executables.

Performance Validator ships in a 64 bit version that can also process 32 bit executables. On a 32 bit machine the 32 bit version installs, on a 64 bit machine both 64 bit and 32 bit versions install, because occasionally there is a 32 bit native bug that you only deal with from the 32 bit version of the tool.

The reasons for this change are

  • .Net applications can be built in 32 bit, 64 bit, and Any CPU versions. An Any CPU version launched on a 64 bit machine will run as 64 bit. To provide full .Net support we couldn’t support Any CPU on 64 bit from 32 bit Performance Validator. The sensible option is to only support Performance Validator in a form that can support both 32 bit and 64 bit architectures.
  • 64 processors are the dominant processors in the market. We should support these by default.

New menu items

To support the new .Net functionality there are some additional launch options for working with ASP.Net applications (IIS and Web Development Server) as well as .Net applications and .Net services.


Launch ASP.Net application using IIS.


Launch ASP.Net application using Web Development Server.


New settings options

The settings dialog has two new panels to allow you to configure .Net Function Inlining and .Net Function Caching. The defaults are the values that an application would normally run with.

.Net Function Inlining


.Net Function Caching


New launch option

With the ability to process both native and .Net applications and mixed mode applications comes the desire to sometimes restrict performance profiling to just native code, or just .Net code, or to allow any code (mixed mode) to be profiled. To handle this we’ve added a simple combo dropdown on the various launch dialogs that allows you to choose how performance profiling is handled at a very high level.


Availability

These changes to Performance Validator will be available after 13 December 2020.

What’s new with Memory Validator

By , December 10, 2020 6:26 pm

There are many changes coming to Memory Validator.

I’m going to describe the various changes and the reasons behind them.

Name Change

The first one is the name change. C++ Memory Validator becomes Memory Validator.

Because Memory Validator will be capable of handling multiple technologies and languages having language specific designators prefixing Memory Validator doesn’t make any sense.

New UX Theme

A new UX theme which is has less visual clutter and is calmer to look at has been introduced. We’ve written about that in New UX Theme.


.Net Support

Memory Validator now supports .Net languages. C#, VB.Net, C++.Net, etc.

.Net Memory Validator is discontinued, all of it’s functionality moving into Memory Validator.

x64 and x86 support

C++ Memory Validator shipped in two versions, a 32 bit version and a 64 bit version that could also process 32 bit executables.

Memory Validator ships in a 64 bit version that can also process 32 bit executables. On a 32 bit machine the 32 bit version installs, on a 64 bit machine both 64 bit and 32 bit versions install, because occasionally there is a 32 bit native bug that you only deal with from the 32 bit version of the tool.

The reasons for this change are

  • .Net applications can be built in 32 bit, 64 bit, and Any CPU versions. An Any CPU version launched on a 64 bit machine will run as 64 bit. To provide full .Net support we couldn’t support Any CPU on 64 bit from 32 bit Memory Validator. The sensible option is to only support Memory Validator in a form that can support both 32 bit and 64 bit architectures.
  • 64 processors are the dominant processors in the market. We should support these by default.

New menu items

To support the new .Net functionality there are some additional launch options for working with ASP.Net applications (IIS and Web Development Server) as well as .Net applications and .Net services.


Launch ASP.Net application using IIS.


Launch ASP.Net application using Web Development Server.


New settings options

The settings dialog has four new panels to allow you to configure what types of .Net data are collected, whether to enable stale .Net object detection, if .Net heap dumps should be collected, and how and when .Net memory snapshots should be made.

.Net Collect


.Net Stale Object Detection


.Net Heap Dump


.Net Snapshots


New launch option

With the ability to process both native and .Net applications and mixed mode applications comes the desire to sometimes restrict memory monitoring to just native code, or just .Net code, or to allow any code (mixed mode) to be monitored. To handle this we’ve added a simple combo dropdown on the various launch dialogs that allows you to choose how memory monitoring is handled at a very high level.


New Summary Display


The summary display provides panels for a particular summary topic with key statistics for that topic displayed in the panel. Panels can display bar graphs, circular graphs and timeline graphs as well as data in table format. Most summaries allow you to click on a data item and be taken to a main tab for the data that was clicked on. This allows the summary display to function as a jumping off point to explore data throughout Memory Validator.

New Memory tab

The new memory tab performs the same function as the Memory tab in previous versions of Memory Validator, but now it contains two sub-tabs. One for viewing native allocations (memory and handles), and one for viewing .Net allocations (memory and handles).

New Statistics tab

The Statistics tab is where all the main statistics data is grouped together. Previously this data was in 3 main tabs: Types, Sizes and Locations. Those 3 tabs are now sub-tabs under the statistics tabs. They are joined by two .Net specific tabs: Generations and Ages, which report information about which generation has how many objects and what ages given objects are. The Ages tab can also report information about stale objects if that functionality has been turned on (off by default as CPU intensive).


New .Net tab

A new .Net tab is where you can find 3 new sub-tabs dedicated to understanding .Net specific memory behaviour. The three sub-tabs are .Net Snapshots, .Net Heap Dumps and .Net Leak Analysis.

New Snapshots tab

The Snapshots tab allows you to take memory snapshots and compare them to other memory snapshots creating memory comparisons. Both snapshots and comparisons can be viewed to identify the location where an object was allocated. You can also use the context menu to then jump to that object in a heap dump reference graph.


New Heap Dumps tab

The Heap Dump tab allows you to view heap dumps provided when a garbage collection takes place. Using the reference graph you can see which objects hold a reference to an object, and which objects an object is referencing. Plenty of options are provided to allow you to restrict the amount of data to wade through (so that you don’t end up with a graph full objects you didn’t build – from 3rd party software).


New .Net Leak Analysis tab

The Leak Analysis tab provides you with a powerful query functionality that allows to query the .Net allocation data to find objects that may be leaked, loitering unused in memory due to references that should have been set to null. We provide many predefined queries, but you can easily build your own queries. Combine with stale object detection data for even more power.


New Analysis tab

The old Analysis tab has been renamed Query and is now a sub-tab of the new Analysis tab. This sub-tab is joined by previous main tabs Coverage, Hotspots, Pages and Virtual.

The Hotspots tab has been updated to include hotspots for .Net memory and .Net handles. The hotspots tab has been moved to a sub-tab on the main Analysis tab.

Timeline updates

The Timeline tab has been updated to include data for .Net memory, .Net handles and .Net all allocations to provide an equivalent to the native timeline views.

Availability

These changes to Memory Validator will be available after 13 December 2020.

What’s new with Coverage Validator

By , December 10, 2020 6:26 pm

There are many changes coming to Coverage Validator.

I’m going to describe the various changes and the reasons behind them.

Name Change

The first one is the name change. C++ Coverage Validator becomes Coverage Validator.

Because Coverage Validator will be capable of handling multiple technologies and languages having language specific designators prefixing Coverage Validator doesn’t make any sense.

New UX Theme

A new UX theme which is has less visual clutter and is calmer to look at has been introduced. We’ve written about that in New UX Theme.


.Net Support

Coverage Validator now supports .Net languages. C#, VB.Net, C++.Net, etc.

.Net Coverage Validator is discontinued, all of it’s functionality moving into Coverage Validator.

x64 and x86 support

C++ Coverage Validator shipped in two versions, a 32 bit version and a 64 bit version that could also process 32 bit executables.

Coverage Validator ships in a 64 bit version that can also process 32 bit executables. On a 32 bit machine the 32 bit version installs, on a 64 bit machine both 64 bit and 32 bit versions install, because occasionally there is a 32 bit native bug that you only deal with from the 32 bit version of the tool.

The reasons for this change are

  • .Net applications can be built in 32 bit, 64 bit, and Any CPU versions. An Any CPU version launched on a 64 bit machine will run as 64 bit. To provide full .Net support we couldn’t support Any CPU on 64 bit from 32 bit Coverage Validator. The sensible option is to only support Coverage Validator in a form that can support both 32 bit and 64 bit architectures.
  • 64 processors are the dominant processors in the market. We should support these by default.

New menu items

To support the new .Net functionality there are some additional launch options for working with ASP.Net applications (IIS and Web Development Server) as well as .Net applications and .Net services.


Launch ASP.Net application using IIS.


Launch ASP.Net application using Web Development Server.


New settings options

The settings dialog has two new panels to allow you to configure .Net Function Inlining and .Net Function Caching. The defaults are the values that an application would normally run with.

.Net Function Inlining


.Net Function Caching


New launch option

With the ability to process both native and .Net applications and mixed mode applications comes the desire to sometimes restrict code coverage to just native code, or just .Net code, or to allow any code (mixed mode) to be covered. To handle this we’ve added a simple combo dropdown on the various launch dialogs that allows you to choose how code coverage is handled at a very high level.


Availability

These changes to Coverage Validator will be available after 13 December 2020.

New UX Theme

By , December 8, 2020 11:49 am

We’ve been working on a new, calmer UX Theme for a while.

The aim is to reduce the number of lines, have less visual clutter, better demarcation of boundaries, consistent colour use across all tools, and to make everything just a bit simpler and calmer to look at.

The best way to show you these changes to show before and after images of each change.

Dialog Titles

Before: Sections are indicated by text with a horizontal line next to it.


After: Sections are indicated by bold text in Software Verify blue with no horizontal line.


Settings grids

Before: Vertical and horizontal grid lines are part of the display.


After: Vertical and horizontal grid lines are minimised with the boundaries between adjacent lines indicated by a subtle change of background colour.


Data grids

Before: Vertical and horizontal grid lines are part of the display.


After: Horizontal grid lines are minimised with the boundaries between adjacent lines indicated by a subtle change of background colour. Vertical grid lines are present, but very subtle so as not to intrude on the display.


Grid highlighting

Before: There was no automatic grid highlighting.


After: When you move the mouse over a grid the line under the mouse automatically highlights in light blue. This can be very useful on wide grids with many columns.


The grid highlighting functionality does not change which items are selected in the grid. It is purely a visual aid. The grid highlighting works for both data grids and settings grids.

Tab Headings

Before: Tabs were displayed with the current tab in bold.


After: Tabs are displayed with all tabs in Software Verify blue and the current tab is bold with the orange highlight colour.


Graphics – Circles

Before: Circles were displayed with outlines and pie section separators.


After: Circles are displayed without outlines and with no pie section separators.


Graphics – Bars

Before: Bars were displayed with outlines.


After: Bars are displayed without outlines.


Splitter Windows

Before: The splitter and the edges of the window were highlighted.

After: The splitter is highlighted. The edges are not highlighted.

Toolbar and menu icons

Before: Our previous icon set was 3D and looked a bit tired.


After: The new icon set is flat and uses the Software Verify colour palette.


Conclusion

These changes in isolation probably don’t look like much, but when you see them all together it makes for a more pleasant experience. The effect is magnified when you’re looking at a lot of data – having less clutter. It’s a subtle but important thing.

These changes will be rolled out across all our tools, both free and commercial, in the weeks following 8 December 2020.

Customers that have purchased tools and that have valid software maintenance will be emailed when software updates containing these changes are available for them to download.

Changes to how we display data

By , June 12, 2020 11:59 am

We’ve changed the display of data on all of our tree controls that are used to display callstacks and call trees.

The old method of display, everything was displayed in black text at normal font weight.

The new method of display, different components of the text are displayed in their own colour, with optional bold, italic, underline or strikethrough, with an optional change in font face. In practice, at present we’re only changing the display colour and turning bold on/off.

We’re using this new display technology to leave some items neutral, emphasise some items and de-emphasise other items. This change has made quite a difference in readability of the display. Right now there is no ability for the user of the software to edit these settings to change the prioritisation and colour scheme we’ve chosen. We’ll provide this capability in a future release.

I’m going to show some before and after images so that you can see the difference for each tool.

C++ Memory Validator

For C++ Memory Validator, we’ve changed both function and filename to be displayed in bold. Type, thread name, timestamp, module name, and symbol name are displayed in different colours. Address is displayed in a de-emphasised colour.

Before


After


Before


After


.Net Memory Validator

For .Net Memory Validator, we’ve changed both function and filename to be displayed in bold. Age, Generation, thread name, timestamp, module name, and symbol name are displayed in different colours. Address is displayed in a de-emphasised colour.

Before


After


Before


After


Thread Validator

For Thread Validator, we’ve changed both function and filename to be displayed in bold. Thread name, timestamp, module name, and symbol name are displayed in different colours.

Before


After


Before


After


Performance Validator

For Performance Validator, we’ve changed both function and filename to be displayed in bold. Module name, and symbol name are displayed in different colours.

Before


After


Coverage Validator

For Coverage Validator, the branches, files and directory displays have had a few tweaks to de-emphasis address information.

Before

After

Bug Validator

For Bug Validator, we’ve re-ordered the display information so that the symbol comes before the filename. Both function and filename are displayed in bold. Timestamp, thread name, module name, and symbol name are displayed in different colours.

Before

After

Memory leak in CPngImage

By , June 1, 2020 9:37 am

A memory leak in a surprising place

We’ve recently been doing some work switching our resources in our programs from BMP (using CBitmap) to PNG (using CPngImage).

At some point we got around to dog-fooding, which we do with our tools all the time, and we were surprised to see memory leaks (in the form of HGLOBAL handles) in our tools being reported by C++ Memory Validator.


We took a look and found they were coming from CPngImage::LoadFromBuffer(). Here’s the code, with the leaking lines highlighted.

BOOL CPngImage::LoadFromBuffer(LPBYTE lpBuffer, UINT uiSize)
{
        ASSERT(lpBuffer != NULL);

        HGLOBAL hRes = ::GlobalAlloc(GMEM_MOVEABLE, uiSize); // this line leaks
        if (hRes == NULL)
        {
                return FALSE;
        }

        IStream* pStream = NULL;
        LPVOID lpResBuffer = ::GlobalLock(hRes);             // this line leaks
        ASSERT (lpResBuffer != NULL);

        memcpy(lpResBuffer, lpBuffer, uiSize);

        HRESULT hResult = ::CreateStreamOnHGlobal(hRes, FALSE, &pStream);

        if (hResult != S_OK)
        {
                return FALSE;
        }

        if (CMFCToolBarImages::m_bMultiThreaded)
        {
                CMFCToolBarImages::m_CriticalSection.Lock();
        }

        if (m_pImage == NULL)
        {
                m_pImage = new CImage;
                ENSURE(m_pImage != NULL);
        }

        m_pImage->Load(pStream);
        pStream->Release();

        BOOL bRes = Attach(m_pImage->Detach());

        if (CMFCToolBarImages::m_bMultiThreaded)
        {
                CMFCToolBarImages::m_CriticalSection.Unlock();
        }

        return bRes;
}

Verifying the memory leak

At first we thought C++ Memory Validator might have made a mistake, as it seemed unlikely that such a well used class would contain a mistake like a memory leak.

To check if this was correct memory leak report or a FALSE positive we created a test program where we can repeatedly create and destroy images in rapid succession. If the leak is real the toy program will soon fail to allocate memory. If the leak is a false positive by C++ Memory Validator, the toy program will run forever with no problems. The toy program demonstrated the leak is real – after just over 65,000 loads of an image with CPngImage, all GlobalAlloc() allocations fail.

The test program allows you to repeatedly load a BMP, a PNG into CPngImage and a PNG into an svlPngImage. The image is destroyed after loading. You can specify how many times to perform the load, 1, 10, 100, 1000, 10000, 64K and 100,000 times.


We have verified that his memory leak is present in all versions of CPngImage that ship with all versions of Visual Studio (up to and including VS2019, we haven’t looked at VS2021 yet).

Fixing the memory leak

The fix is to add two lines just before the return bRes; statement.

        ::GlobalUnlock(hRes);
        ::GlobalFree(hRes);

Unfortunately CPngImage loads it data from methods that are not virtual, so we couldn’t replace them in the implementation. We created a drop in replacement for CPngImage called svlPngImage. It’s identical to the CPngImage class with the exception that the CMFCToolBarImages calls are commented out, and the two additional lines to prevent the memory leak are added. If you’d like to use svlPngImage the source code for this drop in replacement is in the download.

Test Program Source Code

You can download the test program source code and project files.

Update, after response from Microsoft

I was surprised when I got a reply saying this couldn’t happen because the second parameter to ::CreateStreamOnHGlobal() was TRUE. I searched my machine again, and it was FALSE. I then searched a different machine and it was TRUE. So most likely this bug did exist (and we’re using the version of Visual Studio that has it) but has been fixed in a more recent service pack. My claim that the bug was in all versions of Visual Studio was incorrect because I was checking for the absence of the memory freeing calls without checking the value passed to ::CreateStreamOnHGlobal() was FALSE. The drop in replacement class is still valid.

If you’re using CPngImage, check CPngImage::LoadFromBuffer() and if the second parameter passed to ::CreateStreamOnHGlobal() is FALSE, use our svlPngImage class instead. Otherwise carry on as you are.

Update 2, after further response from Microsoft

Microsoft has modified this function to improve the error handling to fix a memory leak if ::CreateStreamOnHGlobal() fails, in response to this bug report, which prompted them to reexamine the function. Ironic in that the report I made, although demonstrating a real bug, that bug had already been fixed, but it still prompted a fresh look at the function behaviour.

Detecting memory leaks in ISAPI extensions

By , April 21, 2020 11:51 am

Three weeks ago I wrote about how to setup IIS for use with ISAPI extensions.

Today I’m going to show you how easy it is to monitor memory and handle allocations in IIS, and use that information to detect any memory and handle leaks that may be present in your ISAPI extension.

IIS is a very secure Windows service. The account security for IIS mean that it can’t access most parts of the Windows filesystem or even Windows objects. CGI and ISAPI extensions will only execute if you’ve configured IIS properly (see the above linked article for details). You can’t launch IIS from a tool like Memory Validator, and you can’t inject into IIS from a tool like Memory Validator because of the security constraints. That leaves you the option of using an API to interact with IIS from your tool of choice.

But I don’t want to use an API!

“But I don’t want to use an API” I hear you say. You’re concerned about having to build multiple versions of your ISAPI. One for use with Memory Validator and one for production. That’s a valid concern, but it’s not the case. You can just build one version of your ISAPI that uses Memory Validator and use that. If you haven’t done “Monitor ISAPI…” from the Launch menu prior to loading your ISAPI the Memory Validator dlls won’t be loaded. There is no dependency on Software Verify DLLs, you can ship your DLL without any need to ship the Memory Validator DLLs.

But should you need to examine memory allocation behaviour you can just fire up Memory Validator and get to work without making a special build.

ISAPI API

ISAPI extensions provide 3 APIs for IIS to use:

BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer);

BOOL WINAPI TerminateExtension(DWORD	dwFlags);

DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB);

GetExtensionVersion() is called when the ISAPI is first loaded. We’ll use this to load Memory Validator into IIS.

TerminateExtension() is called when the ISAPI is unloaded. We’ll use this to tell Memory Validator that the work with IIS is done.

HttpExtensionProc() is used to process any requests made to the ISAPI extension.

Memory Validator API

To add the Memory Validator API to the ISAPI we do the following to the ISAPI source code:


  1. Add two header files:

    #include "svlMVStubService.h"
    #include "svlServiceError.h"
    

  2. We add the following code to GetExtensionVersion(). This includes logging success and failure so that we can identify if anything has gone wrong. Without the logging determining failure inside of IIS is very hard (a debugger and a special build of the Memory Validator DLL is required).

        // load Validator here
    
        svlMVStub_setLogFileName(L"C:\\testISAPIWebsite\\svl_MV_log.txt");
        svlMVStub_deleteLogFile();
    
        SVL_SERVICE_ERROR   errCode;
    #ifdef IS6432
        // x86 with x64 GUI
        errCode = svlMVStub_LoadMemoryValidator6432();
    #else   //#ifdef IS6432
        // x86 with x86 GUI
        // x64 with x64 GUI
        errCode = svlMVStub_LoadMemoryValidator();
    #endif   //#ifdef IS6432
        if (errCode != SVL_OK)
        {
            DWORD   lastError;
    
            lastError = GetLastError();
            svlMVStub_writeToLogFileW(L"C++ Memory Validator load failed. \r\n");
            svlMVStub_writeToLogFileLastError(lastError);
            svlMVStub_writeToLogFile(errCode);
    
            svlMVStub_dumpPathToLogFile();
        }
        else
        {
            svlMVStub_writeToLogFileW(L"C++ Memory Validator load success. \r\n");
    
            errCode = svlMVStub_StartMemoryValidatorForIIS();
    	if (errCode != SVL_OK)
    	{
                DWORD   lastError;
    
                lastError = GetLastError();
                svlMVStub_writeToLogFileW(L"Starting C++ Memory Validator failed. \r\n");
                svlMVStub_writeToLogFileLastError(lastError);
                svlMVStub_writeToLogFile(errCode);
    	}
    
            svlMVStub_writeToLogFileW(L"Finished starting C++ Memory Validator\r\n");
        }
    

    You’ll need to edit the location of the logfile to match the name of your website directory.

  3. We add the following code to TerminateExtension().

        // unload Validator here
    
        svlMVStub_UnloadMemoryValidator();
    


Monitoring memory allocations

Start Memory Validator.

From the Launch menu choose the IIS sub menu and then Monitor ISAPI….

The monitor ISAPI dialog is displayed. Any settings from a previous launch are displayed. Edit the settings appropriately.

You need to identify the ISAPI dll that is being processed, the website directory, the IIS process (choose Any IIS if you don’t know or don’t care), the web browser (the default is Microsoft Edge as it seems more tolerant of data format errors than Chrome) and finally the URL you wish to use to test the ISAPI.

Click OK.

Memory Validator copies some DLLs to the directory containing the ISAPI, sets up various variables that will be used inside the IIS process, resets IIS, and launches the web browser to load the specified URL that will load the ISAPI.

When you’ve finished interacting with the ISAPI, you’ll need to stop IIS. Go to the Launch menu, choose the IIS sub menu then Stop IIS.

When IIS has stopped executing Memory Validator displays “Ready” on the status bar, the Memory tab will show any memory leaks and handle leaks that are present.

A short video of this process is shown below.

Conclusion

We’ve completely reworked our ISAPI support so that you have very little to do, just use the API as shown above and launch using the Monitor ISAPI command.

In comparison, here are some instructions for using Boundschecker with IIS. These are out of date and will no longer work. But look how much you have to do manually.

Panorama Theme by Themocracy