By Reg Charney
Contrary to the title, I hope to make this a little treatment a little fun. The first example comes from a manual on Q&A Software. See if you can identify the error:
| void testFcn() { char *aPtr; for (int i=0;i<500;i++) aPtr = new char[100]; delete [] aPtr; return; } |
The manual explains:
“In this instance, only the memory allocated the last time through the loop is freed. The other 499 times, memory was allocated, the resulting pointer assigned to the same pointer. (aPtr), but not released. If you follow the program in debugging mode, you’ll see that after each call to new, aPtr has a different value. Using the same pointer variable each time you allocate memory does not automatically free the memory that was associated with it before. You must free the memory explicitly.”
It is true that there is a memory leak, but the simple solution is to enclose the two statements following the for in a pair of braces.
The next error is more subtle than the last one. Herb Sutter and Jim Hyslop (www.gotw.ca) wrote a light-hearted article on thread safety. A fragment like my simplified example appeared:
| class Car { explicit Car(); private: ostream& Ins(ostream&); friend ostream& operator<<(ostream&, Car&); Mutex m_; string rep_; // ... }; ostream& operator<<(ostream&
o, Car& c) ostream& Car::Ins(ostream&
traffic)
|
Here the problem concerns the use of the Mutex m_ inside the Car class.
Herb explains the three errors this way (excusing the Shakespearean English):
“Thou shalt not make objects thread-safe — it is a perversion. Thread safety is good, but now every Car in the system will incur the evil lock overhead whether that Car object is actually ever used by more than one thread or not. This was one of the mistakes in the early so-called ‘thread-safe’ Java containers. Those designers soon learned the errors of their ways. If an object can be used by multiple threads, it is the responsibility of the outside code that owns that object, and that code alone, to serialize all access to it. This too is encapsulation and a striving after correctness.”
For a fuller treatment of this whole subject, see his online article at http://www.gotw.ca/publications/optimizations.htm.
On the ACCU-GENERAL mailing list, the following question appeared:
“Why does the [following Java] switch give the error message "<identifier> expected?"?”
| switch (arrInts.[at]) { //... } |
James Dennet <jdennett@acm.org> gave the following answers:
If it's not an array, in Java you must use arrInts.at(index) or similar; Java lacks operator overloading, except for + on Strings, so you can't have classes looking like built-ins.
However, I believe that this is another case of poor error diagnostics. My first reaction was “What identifier?”, That is, where is the identifier expected: before or after the switch keyword, in the expression, or after the switch expression. A much better error message would have been: “Scalar expression expected in switch clause.” To quote The Java Programming Language, 3rd Edition by Ken Arnold, James Gosling, David Holmes published by Addison-Wesley Pub Co; ISBN: 0-201-70433-1:
The switch expression must be of type char, byte, short, or int. All case labels must be constant expressions - the expressions must contain only literals or named constants initialized with constant expressions - and must be assignable to the type of the switch expression.
Most of you are not members of the ACCU, so you do not have access the ACCU-GENERAL mailing list. I thought you might like to listen in on a short exchange recently.
Why is it good to do this: std::string or std::vector
I’ve noticed in many articles, authors insisting on writing fully qualified names for members of the standard library, instead of applying 'using directives' or 'using declarations'. Can somebody please explain why this is encouraged? Should it be encouraged?
—Michael
I'd encourage it for two reasons:
There can be times, in writing template code, where the uncertainty over which name will be chosen when using a using declaration can be handy. Most often, though, you know that you want the std version, so why not say it in the code?
There are those (not including myself) who think that the std:: is visual clutter, and hinders clarity. I guess that's subjective.
—James
You're not alone, I always explicitly qualify my names. I believe it makes the code more readable since it leaves no question where the name comes from. If for instance someone else were to read your code and they came across a name they weren't familiar with they wouldn't have to search for the declaration/definition. They could instead pick up their copy of “The C++ Standard Library” or documentation of any third party library as it would be far more obvious where the name originates. A using directive does not help identify such names and although a using declaration might be of slightly more benefit it still has to be searched for.
Another reason I avoid using directives is that they are transitive. A using directive that nominates one namespace may in fact nominate several which is not immediately clear without searching the namespace itself. I.e.,
| namespace A { //... } namespace B void f(void) |
If anything this reduces readability. Another example of confusion:
| template <typename
T> class vector { T* ptr; }; int main(void) error: 'size' : is not a member of 'vector<int>' |
Wouldn't that leave someone scratching their head for a while? But wait a second ....
| int main(void) { using std::vector; vector<int> vi; int s = vi.size(); return 0; } |
All is well now! Lookup rules differ depending on whether you use a using directive or using declaration.
| int main(void) { std::vector<int> vi; int s = vi.size(); return 0; } |
Ah, much better! :-)
—Rob
A question regarding traits
When creating a traits class one can use of the following two conventions
| struct SomeTraits { static const int error_code= -1; }; |
or
| struct SomeTraits { static int error_code() { return -1; } }; |
Now obviously the above example is over-simplified, but the question here is: What are the list members' preferences to using functions in traits to return constant values vs. using ‘static const’?
(Possibly a real world example to refer to is the eof() in std::char_traits).
—Schalk
There's an obvious difference between the two, in that the first example may be used in compile-time computations, while the latter can't be used there. For example:
--- Start ---
| struct TraitF // use
fcn { static const int val() { return 1; }; }; struct TraitV // use value int main() |
--- End ---
Note, some compilers (such as VC++) don't handle in-class initialization of static constants, so you may have to use the “enum-hack”, instead:
| enum { val = 1 }; |
Also, such constants only work for integral types, not floating point values or pointers.
—Terje
My application doesn't get to main()
I have an application that uses at least two dynamic libraries, and it works fine in one environment but not another. I'm unsure what to check now; I don't really understand how dynamic libraries work, and so I don't know where to begin finding out what is wrong.
--Michael
Not enough information!
What environments? What specifically is the problem? How do you use dynamic libraries? How are you linking?
You say it “doesn't even get to main” - are you sure you have linked main in? Why do you think this is related to dynamic libraries?
—Dave
If it's in Windows, you can use the DevStudio’s Depends utility to see if it's not happy with either of your DLLs. This might be because it can’t find them (path problem), or they have a dependency which is not resolved (e.g. they use an OS function which is not in your different environment) and therefore can't be loaded.
—-Simon
Well, as a first step, tell us what the platforms / environments you are working with are. If it's a UNIX platform, you'll want to check out the LD_LIBRARY_PATH variables; also, the ldd tool will be invaluable.
There are similar things on Windows, but it's been a while since I've done any serious work on that platform. So, the more details you can give us on the context and the problem, the easier it'll be for us to help you out.
—Burkhard
I'm going to guess that you'd on Windows, as some else pointed out you have ldd and a host of LD_LIBRARY_ environment variables if your on Uni*.
Typically I find this when you have an app which loads a DLL, which in turn loads another DLL. When the first DLL fails to find the second DLL you get "Cannot load library" (or something similar) in a model dialog box and you pull your hair out because you can see the DLL (the first one) is there.
Things to try:
then there is a Windows tool called “depends”, in the resource kit I think — actually there are two versions of depends, a command line one and a GUI one, you want the GUI one. It will allow you to look at a DLL and see what it is loading.
Try setting a break point on mainCRTstartup and see what happens
And if none of that works come back and give us some more info.
—Allan
By Reg. Charney
I am writing this column from Israel. I came because I felt that I needed to do something here to lessen the violence. I came here with several ideas to get both sides talking. One main idea was that there needs to be common ground. Since I despaired of governmental agencies communicating — they had too many vested interests, I needed to reach beyond them to the people themselves. This has proven to be very difficult. The distortion field here is immense. Both sides are affected and each side sees things almost totally in its own terms. The Israelis see only innocent victims and madmen. The Palestinians see suicide bombers as heroes and any strike against the domineering Israelis, whether men, women or children, as legitimate targets. I believed that there is one major problem: the average person has no control over the honesty of the information they get that to solve the problem, we need establish one-on-one relationships between members of the opposite side.
However, the facts are more frightening than I imagined. There is a well-respected organization, the Palestinian Center for Policy and Survey Research (www.pcpsr.org), here that has done a very credible job of conducting public opinion surveys of both the Israeli and the Palestinian populations. Since I am here trying to reduce the conflict long term, I was interested in the following questions and the responses from the last survey done December 2001. Amongst the Palestinians, the level of support for attacking Israeli solders and settlers is 92%,, for attacking civilians inside Israel is 58%. A Palestinian majority of 61% support armed conflict. On reconciliation, only 6% of Palestinians support changing the school curriculum to recognize Israel’s right to exist. Amongst Palestinian, 91-98% view all Israeli violent acts as terror acts. while 81-87% do not view violent acts against Israelis as acts of terror.
How do we reconcile these differences?
Programming with Qt, 2nd Edition. By Matthias Kalle Dalheimer, O'Reilly Verlag, GmbH und Co. KG 2002, ISBN 0-596-00064-2
This book is an absolute ‘must read’ for every Qt programmer and strongly recommended for anyone facing the task of building advanced GUI based applications. The book requires an intermediate level of experience with C++ and understanding of object oriented development principles.
Qt is a C++ class library providing a platform independent GUI toolkit. Kalle describes and explains the important components of the Qt toolkit while keeping an eye on the big picture of good software practices.
Using this extraordinary toolkit, the author needs just two chapters after the introduction to show how to design and implement a nontrivial application with some advanced user interaction. A chapter about Qt's sophisticated and elegant layout managers concludes the first part of the book.
Kalle then shares his valuable insights about GUI design. This may not belong here, but I am grateful for this advice.
The second part of the book covers the many possibilities that the Qt toolkit provides including container classes over graphics with and without OpenGL; multithreading; and Qt network programming.
A chapter about interfacing Qt with Perl, a chapter about using and integrating Qt with the Visual Studio IDE as well as a thorough introduction to the graphical interface builder 'Qt Designer' conclude the book.
The book’s last two chapter, belong in the front and the initial examples should make use of Qt Designer and Visual Studio rather than bore the reader with the idiosyncrasies of the Unix command line or scare him with ‘make’.
— Dr. Roland Krause
By Reg Charney
A number of things conspired to make this month’s Trend column disappear. I am currently out of the country and the raw data gave no clear indication of where the trend lines were going. This made drawing meaningful conclusions difficult. From other sources, we know that the Valley has been hit particularly hard since the Internet Bubble burst. Trends will be back next month.