C++ : The new and delete operators
March 21, 2009
If you have been accustomed to C, you may encounter the way heap memory is allocated:
char* c = (char*)malloc(sizeof(char) * x);
In C++, due to the existence of classes and constructors/destructors, malloc and free alone won’t suffice; it won’t be able to call the constructor and destructor, respectively. So, the keyword new was made to allocate the memory and call the constructor. The previous item will now look like this:
char* c = new char[x];
Notice that sizeof(char) is gone. Why? Because new will, in order to return the correct pointer type, need to know the type of data you are allocating, and the operator determines the size of an element from the type. The general syntax of the new keyword is:
<data type>* x = new <data type>[y];
where x is the pointer to store the address of the allocated memory, and y is the number of elements. When y = 1, the [y] part can be omitted:
<data type>* x = new <data type>;
Notice new’s two forms: the former, with the square brackets, is called vector new; the one without the brackets is called scalar new.
On the other hand, delete does the reverse: it calls the destructor before putting the memory back to the heap. The delete operator has two forms:
delete – for single-element allocations (scalar)
delete[] – for multi-element (array) allocations (vector)
To avoid being too technical, as I’ve done in some posts, the versions with the square brackets are for array (vector) allocations/deallocations, while the versions without the brackets are for one-element (scalar) allocations/deallocations.
.NET Framework runtimes and legacy computers
March 8, 2009
We may have heard of the .NET runtime in one form or another. Some applications require it in order to run, and many user-interface components out there rely on that framework. But I’ve found out, to my disappointment, that Windows 2000 (or XP) and earlier do not have it pre-installed.
The .NET framework is a significant installation on any machine (a check in the Control Panel applet will easily show how bloated it is, ~100 MB for v2.0), and though speed and performance isn’t much of an issue on newer computers, I tried installing it on an older computer I have at home, and my computer’s slowing to a crawl. Besides, I think v2.0 of the network requires Windows 98 or later – it’s fine, since it’s built with MSVC 2005 and that compiler has a minimum OS requirement of Windows 98, to say the least. The real thing I don’t like is v3.5 . It’s built with MSVC 2008, and, as I’ve said in an earlier post, requires Windows 2000 or later.
One important item to point: in industrial automation, the time used for executing MSIL code often isn’t tolerable.
I guess the v3.5 runtime is bloated more than twofold over v2.0. The latter’s already fine for me, so why install a newer one?
There aren’t any issues with the .NET framework under Vista, since they’re pre-installed. To say, though, I, like many other users, don’t like Vista – it’s bloated on two sides: disk usage and memory usage, and the more important issue is compatibility.
Even with the v2.0 framework installed on my machine, I still stick with developing native C++ code, with a VC2005 compiler (since I recently began hating VC2008), and I can use Adobe Flash for my UI needs.
And I’m making all of my DLLs in my libraries in native x86/x64 code.
A brainteaser: brainf*ck
February 13, 2009
I came across a programming problem one day; it was a problem used in ACM 2005. The problem: making a brainf*ck interpreter. It’s really going to f*** up your brain if you program in it manually, hence the name.
I found a fun use of it: encoding of text files. It’s easily capable of bloating a text file’s size, while making the result jumbled. It uses only one cell out of the standard’s 32768.
Here are a few programs written in Brainf*ck:
->++++++++<[.>.<-] % Prints all ASCII characters in reverse, while emitting a beep for each character
++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++<[>.+<-] % Prints the numbers 0-9
++++++++++++++>+++++++<[>.<-] % Beeps 14 times.
Enjoy!
Visual C++ 2005/2008 and Manifests…
January 18, 2009
It is interesting to see how Microsoft put a lot of effort in isolating DLLs to solve the long-hated problem of “DLL hell” (wherein a program depends on an exact version of a DLL, no newer, no older.) This, however, also brings a problem: security updates may not be propogated to older DLLs.
Take the Visual C Runtime DLL, msvcr80.dll , as an example. Its internal structures haven’t changed with every build. The problem here is that side-by-side lookups in XP and Vista check the versions to the build number, and ignore the DLL if its version numbers are different, even a build number. So there is a possibility that security updates with newer builds (e.g., 8.0.50767.163 from 8.0.50767.42) will not be propagated to the older versions.
Worse, if the application has no manifest (e.g., legacy apps) or the version numbers indicated in the manifest and the DLL’s numbers do not match, the result will be an initialization failure at start-up (because the CRT DLL will fail the initialization routines upon detecting either of the two conditions mentioned.)
Like I’ve mentioned in a previous entry, having two different CRTs in the same application will most likely catch the end-user by surprise, through such messages as fatal CRT memory corruption. I’m still developing the “proxy” CRT (this one is NOT the actual CRT; the actual CRT is Windows’ system CRT, msvcrt.dll .) Note that I do not use manifests in the “proxy” CRT DLL; let all applications, older or newer, get the security update.
Visual Studio 2008 and Application Compatibility
January 4, 2009
I’ve noticed that Microsoft has stopped supporting the entire Win9x series (those that run on top of DOS – Win95, Win98, WinME) in VS 2008. Also, a few global variables have been removed (such as _winver). In my opinion, these allowed the programmer to get OS version numbers right using the CRT. That’s easy, at least for me.
If I’m not mistaken, VS 2003 was the last to support Win95; and VS 2005 (which I am using) was the last to support Win98/WinME. With VS 2008, you are forced to target Win2000 or later (WinNT 4.0 is not supported). But maybe the developers of Visual Studio should be aware that these “legacy” Windows OSes are not yet shelved up for indefinite storage (maybe Win95 on the shelf will not be a big suprise, but Win98 systems still exist up to this day, in PCs used for automation, for instance.)
Windows 98 was used in automation computers, since this ran on top of DOS, and DOS allows a program to directly access the hardware via simple memory location reads/writes. This functionality is important with certain applications of automation wherein direct hardware control is a must; an example maybe a part of a power plant.
Windows NT/2000/XP have the additional advantage of security; although this helps prevent hackers from breaking into the PC and turn it into a “zombie,” these security checks may unnecessarily slow down the program, and may sometimes become detrimental .
Note that I think Windows 95 is not used on a single computer (Even most Win9x-only devices don’t support Windows 95.)
Well, we are at the mercy of Microsoft, since they can do whatever they want – even breaking compatibility with existing applications (this is what they did in Windows Vista, using User Account Control.) But Microsoft shouldn’t do that breaking – eventually, customers will not buy a new version of their Windows operating system if they know their current applications won’t work on that new version of the OS; it’s very likely Microsoft’s efforts on improvement (such as security) will go to waste, since customers aren’t going to use the new version.
You may think of me as a hypocrite (since I’m now using Visual Studio 2008), but I’m trying to generate a Visual C++ 2008 CRT DLL proxy to the system CRT using Visual C++ 2005 (because this version, at least, supports Windows 98/ME in any case. I still have that copy installed on my PC, although only the Express Edition.)
I like compiler upgrades for their security, but I don’t like them if they are going to break support for Windows versions that are still in use (Windows 98, 2000, XP, Vista), and a workaround is virtually impossible.
On the Visual C++ .NET DLLs…
January 2, 2009
One would notice that many applications compiled with Visual C++ 2002 or later would have the Visual C runtime DLLs in their private folders. As mentioned in KK’s blog, this approach doesn’t allow for central servicing.
Examine the code of one differential CRT DLL (say, msvcr90.dll), and that of the Windows CRT DLL (msvcrt.dll) – many of the functions haven’t changed through the years. This results in duplicated code in two different binary images, which wastes space. Exception handling can change, yes, but many of them still reference C Library functions (which hasn’t changed).
In that light, I decided to write a “proxy” DLL to make them use the Windows OS CRT.
There is one more common issue when using “legacy” DLLs (those compiled with VC6) with images produced by the VC7+ compilers: Heap corruption. Each CRT instance has its own heap, and even passing pointers between two different instances of the same identical CRT DLL is very likely going to result in a runtime failure. Examine again a differential CRT DLL with the Windows CRT DLL, and you will find that memory allocation functions (such as operator new[] and operator delete[]) are duplicated. To eliminate this problem, I also decided to use the Windows CRT’s memory heap instead and provide code-wraps and forwards required by the new VC7+ code.
By the way, I would greatly appreciate contributions in finding the functions that have been added after VC6.
Visual C++ 2005 and MSVCRT.DLL
December 15, 2008
Thanks to KK for his help.
I just notice a few things while linking to msvcrt.lib in the 2008 WDK:
~ If you were statically linking to the C++ library (libcpmt.lib), there is this error of this unresolved external symbol:
__calloc_crt referenced in __Getctype
so I browsed through libcmt.lib. Alas, my problems got worse, so I was forced to write my own copy of this function.
My code appears here, in blue:
#include <stdlib.h>
#include <malloc.h>
extern “C” void* __cdecl _calloc_crt(size_t a, size_t b)
{
return calloc(a, b);
}
I notice this code works perfectly I use it, but as always, no piece of code is correct for everyone.
~ Also, you may get an unresolved function at runtime:
_except_handler4_common could not be located in Msvcrt.dll .
It is because, as was mentioned in KK’s blog, this (plus a bunch more) is only available in the Vista version of the CRT DLL. So, I pilled some .obj files from libcmt.lib and compiled them into one library; they work as expected. I will post the library online some time.