Click to See Complete Forum and Search --> : Memory Allocation 16 Bit vs 32 Bit Windows
wdolson
June 15th, 2010, 05:23 AM
I am finishing the port of a suite of Windows programs that were originally released under Windows 2.0 (they started development under Windows 1.0, I've found many comments dated 1986!). These programs allocate and deallocate memory all over the place. Way more than is necessary, but they were probably trying to fit into the small physical memory on PCs back then.
I'm campaigning to rewrite the whole suite into one integrated program, but I haven't convinced them it would be cheaper to start over yet.
Anyway, one thing that is causing a lot of problem is allocated memory shared between applications. One program will allocate the memory, possibly do something with it, then send a message that another application picks up, grabs the shared memory, does something with it, then the original program continues.
In a lot of places, the second program is hanging because the memory passed to it is locked when it gets it. In some cases the sending program does a GlobalUnlock before sending the message to the receiving program, but it still arrives locked.
I was able to get it to work by calling:
addr = MapViewOfFile(sharedHandle, FILE_MAP_ALL_ACCESS, 0, 0, viewSize)
Then looking at the second DWORD which is the flags and manually clearing the lock flag if it's set. I'm concerned I may be doing something that might destabilize the program though. It's kind of a kludge.
The programs use GlobalAlloc, GlobalLock, etc. as well as the LocalAlloc, etc. functions. From what I've read, these old function calls are now just wrappers to the current heap functions and there really isn't Global and Local memory anymore.
I'm also wondering if the lock flag is set upon allocation in the Win 32 alloc functions, but is not locked by default in the Win 16 functions? Something systematic is definitely going on that is different in Win 32 and Win 16. I'm just guessing this is it.
wdolson
June 16th, 2010, 09:18 PM
RESOLVED
It looks like the programmer who started the 32 bit conversion wrote a bunch of code that never got debugged. That was 5 years ago and the only person left who was associated with the project is not a programmer.
There was one function call that created a file map for communication between programs, then another function was called soon after that locked the memory, among other things. I was assuming the code was pretty much the same between the 16 and 32 bit version and wasn't looking for this sort of thing.
Arjay
June 21st, 2010, 01:31 PM
In my opinion, the 16-bit program needs to be rewritten for 32-bit. There enough differences between the two that maintaining a converted 16-bit program would be a nightmare.
Essentially, you need to start over and take advantage of what 32 bit has to offer (threading, security, etc).
Also, 64-bit is already here. If you rewrite it for 32-bit now and follow some simple guidelines, porting it to 64-bit in the future will be more or less a simple recompile.
wdolson
June 21st, 2010, 05:48 PM
I'm campaigning hard for a complete rewrite. They have a service contract with a customer and will lose money if they don't deliver something updated every three months. My guess at this point is a complete rewrite would take about 6 months.
The two areas that are most complex about the existing code will be completely eliminated with a rewrite. The first is scheduled to be removed later this year, it's a custom file system that was designed to get around the 8.3 file naming limitations in Windows before Win 95.
The other area is the code for communicating between the different EXEs. If they were different views in one unified program it would be vastly simpler.
At this point they are considering the rewrite at the end of the year, even if they have to renegotiate with the customer. Most of the work on the file system fix would have to be done for an all new program anyway.
Fixing these bugs with the conversion is a bit of a wasted effort if we do a rewrite, but I am learning how it works which will make a rewrite easier down the road.
Some parts of this code are ancient. I found one comment about a piece of code that was done to get around a bug in Windows 2.0. I stripped it out and the bug I was chasing was partially fixed.
I've worked with some pretty ancient systems. I started out maintaining a Z-80 based system originally written in 1977 (back in the late 80s), but I've never dealt with anything this archaic trying to run on modern hardware.
Bill
Arjay
June 21st, 2010, 06:05 PM
I've done a few of these ports (um rewrites) over the years.
One of them retrieved data from a barcode scanner via the serial port. In the original 16-bit app, they always had data transfer problems and used a fairly low baud rate. Even with the low baud rate, there could be some data loss while communicating with the scanner if the user was doing something with the UI (moving the mouse around, etc.).
The 32-bit version of the app that I developed put all the serial port communication into a worker thread. One time while I was demoing the functionality to the customer, while retrieving data from the scanner I was sitting there idly moving the mouse around and one of the customer techs kind of freaked out saying "you can't move the mouse around while retrieving data!!!". At first I didn't know what they were talking about, but then realized in the 16-bit app, moving the mouse would interrupt the serial port data retrieval. Of course, this problem no longer existed in the 32-bit world - especially since I made the serial port thread run at a slightly priority than the UI thread, so pretty much nothing the user could do in the UI would interrupt the data transfer - well other than cancelling the operation or closing the app <g>. Had I only been able to directly port their code to 32-bit, they never would have had this long standing problem correctly.
We're on the same page here - if the customer could agree to a rewrite, it would be in their best interest.
dexblack
July 5th, 2010, 11:37 PM
Here is my formula for dealing with legacy code.
//#define MY_NEW_API
#if !defined(USE_MY_NEW_API)
Then you can
#define a set of macros that span the existing functionality
or write class wrappers for the current functionality.
Replace the existing method calls that are to be reimplemented with macros and/or class wrappers.
Write a clean(er) set of interface(s) for the functionality being reimplemented.
#else
#define the same set of macros that utilise the new calls
or reimplement the wrapper classes using more robust coding techniques (logging, exceptions etc.)
#endif
Implement reusable, thoroughly unit tested replacements for the nastier pieces of the existing program.
When the the new macros and underlying components are ready throw the switch by uncommenting
#define MY_NEW_API
It is often useful to put the two implementations (old vs new) in separate header files in order to allow easy comparison and deletion of the legacy code when you're done.
Arjay
July 6th, 2010, 12:37 AM
My formula for dealing with legacy code is to throw it away. :)
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.