Letters to the editor may be sent via email to [email protected], or via the postal service to Letters to the Editor, C/C++ Users Journal, 1601 W. 23rd St., Ste 200, Lawrence, KS 66046-2700.
Dear CUJ,
First of all, I would like to thank you and the CUJ team for creating such a wonderful publication. I look forward to receiving it every month and immediately devour every single word.
Secondly, I would like to plead with you to not go the way of VCDJ. I used to have a subscription to VCDJ, but they slowly moved to C#, COM, etc. The past few issues I received, I could not find a single article I found interesting or remotely practical. So I canceled my subscription.
I consider myself a well-versed developer, but a practical one as well: C/C++, SQL, Perl, PHP, Java, etc. However, I avoid platform-specific technologies, since I find them to be too limiting in most cases.
I can only hope that the C# article was not foreshadowing a slow decline into the dark and dreary realm of VCDJ.
Thanks,
Justin Kirby
We appreciate the praise and the warning. CUJ will continue to be primarily concerned with C and C++. Since C# is a language related in some way to both, we will occasionally run articles about it, like we have Java in the past (which now appear mainly in our Java Solutions supplement). But dont worry, we keep our eyes on the mainstream. Thanks again. cda
Hello,
In the May 2001 issue there was an article about sockets (Two Classes for Simple Socket Programming by Richard Smereka). I downloaded the code from <www.cuj.com> from the archives just today, and I noticed an error in the file flsocket.h. Instead of #define NO_FLAGS 0, you have #define NO_FLAG 0. This is a small error, but stops the sockets from being compiled.
Thanks,
Jordan Wilberding
Jordan,
This error was noticed too late to be corrected in the magazine article. You are correct. NO_FLAG should be changed to NO_FLAGS in the header flsocket.h.
Rick Smereka
Mr. Chuck Allison,
I have read your article, import java.*: Threads 101 in the Java Solutions supplement to C/C++ Users Journal (June 2001). You mention communication through callbacks in the summary.
I dont know the meaning of communication through callbacks with threads.
Please let me know where I can find the materials concerning callbacks with threads, and in addition, the concept of thread pooling.
Thanks in advance.
Koji Kotaki
A very good explanation is in the Threading chapter of Elliotte Rusty Harolds book, Java Network Programing (OReilly & Associates, 2000). Also, see the books Java Threads by Oaks (OReilly & Associates, 1999), and Concurrent Programming in Java, Second Edition, by Lea (Addison-Wesley, 1999). cda
Dear Mr. Allison,
Regarding your editorial complaint of August 2001 (about the misuse of functor), I think you are forgetting that youth changes the language. What was once a bundle of sticks became a derogatory term for person of the same sex persuasion. So to what was once a transformation that mapped a function to a function has become a class with an operator, which has as its sole purpose been a replacement for a free standing function with local memory, functor.
Language changes over time and old timers cringe, such it has always been. No amount of complaint will stem the tide.
Sincerely,
Gary Powell
Dear CUJ,
In the August 2001 issue of CUJ, I see that things like realator make you cringe. Then I see in the August 2001 Java Solutions a guy named Chuck Allison crowing that Allen Holub (good choice, btw) ...will take the reigns as editor.... Does this imply that Allen has a split personality, or that he will succeed himself concurrently, or some other, trickier route? (See <www.dictionary.com/cgi-bin/dict.pl?term=reign>.)
I can see how the editor might think of himself as the exerciser of sovereign power at times (bit of a circular definition that), but plural? Maybe you meant <www.dictionary.com/cgi-bin/dict.pl?term=rein>. Two of which are commonly used to steer a horse?
Hoist by your own petard (French for spell checker), so to speak?
David Callaway
Good eye! You got me good!
The cringing was not so much against human error (realator) as much as it was against muddying the waters of technical terminology (functor). But thanks for the zinger! cda
Chuck,
Your otherwise excellent article import java.*: Threads 101 in the June 2001 issue of Java Solutions was flawed by the mention of the pronunciation of the word daemon as being DAY-mun. Check your dictionary the word is a variation of demon and is pronounced DEE-mun. (See the online Merriam-Webster dictionary <www.m-w.com/cgi-bin/dictionary?book=Dictionary&va=demon>.) It uses the rare ae vowel combination, as do the words Caesar, antennae, florae, aeon, aegis, and many other words derived from Latin. The ae in all of these words is pronounced ee, not ay.
The inventors of daemon processes, going back to the early history of CTSS, chose the word to specify a special class of processes that ran continuously in the background, such as print spoolers and communication gateways. I suppose they preferred the more archaic looking daemon over the more modern demon probably thinking the former would have less negative connotations. They pronounced it DEE-mon, by the way.
Ive often heard daemon mispronounced, and Ive done my best to correct the speaker at the time. Please dont promote this particular illiteracy any further.
Other links:
<www.ctrl-c.liu.se/~ingvar/jargon/d.html#daemon>
<www.tuxedo.org/~esr/jargon/jargon.html#daemon>
<www.funet.fi/pub/mirrors/wombat.doc.ic.ac.uk/foldoc/Dictionary>
David R Tribble
Guilty as charged. I succumbed to trusting a certain book, when in fact I had pronounced it correctly way back in my Unix days. As another reader suggested, the Devil made me do it! Thanks for setting me (and hopefully others) straight. cda
Dear Chuck,
First, I would like to congratulate you as being named Senior Editor of C/C++ Users Journal. Ive been subscribing to the journal since 1994, and Ive also enjoyed attending your seminars at the SD conferences over the past four years.
I facilitate a Java Users Group here in New Jersey (please visit <www.redlich.net/javasig/> for more info), and I was asked an interesting question at the last meeting. It had to do with the use of the this function call in the default constructor versus using setter methods with default values. Here is a snippet of what I mean:
class Rational { ... // default constructor public Rational() { this(0,0); // setNumerator(0); // setDenominator(0); // setResult(0); } // primary constructor public Rational(int numerator, int denominator) { setNumerator(numerator); setDenominator(denominator); setResult(numerator, denominator); } ... }
Is there really any difference using this(0,0) in the default constructor over just calling the setter methods? The only thing I can think of is an additional function call because this(0,0) will call the primary constructor, which calls the three setter methods there.
Thanks in advance for your help.
Regards,
Mike Redlich
I dont see a noticeable difference. You might generate the byte code and inspect it just for fun. I assume you know that all primitive members are zero-initialized anyway, so the no-arg constructor is not necessary at all. If that is not to your liking, you can always use an anonymous, non-static constructor block as a shared constructor. See my July 1999 CUJ column, import java.*: Thinking in Objects (<www.cuj.com/java/allison/july99.htm?topic=java>). Cheers cda
Hello,
I read you editorial in the August 2001 issue of Java Solutions and your request for readers thoughts on productivity in Java. Truthfully I was shocked that no one had responded to Marcs original inquiry, so I decided I should throw my two cents in.
My time at work is split (almost evenly) between writing in Java and C++. Personally I would rather work full time in C++ (better development tools, the language is more versatile, etc.), but I certainly dont mind working in Java.
The library support in Java makes life much easier when it comes to certain types of programming. Internet/socket programming immediately comes to mind. Although there are libraries in C/C++ to accomplish the same tasks, the Java libraries are standard, and that makes it easier to look at code examples that use it, because it will be implemented pretty much the same from programmer to programmer. Also, a lot of thought was put into Javas I/O mechanisms, and the socket libraries show this by how well the fit together.
Granted, the Java libraries are cumbersome and hard to get used to, but a wealth of documentation exists on the Web, and it is usually pretty easy to find the information you are looking for.
My only real complaint about Java is the garbage collector. I understand and appreciate the concept of trying to keep the developer from leaking memory, but it really makes me uncomfortable to just trust the JVM. I suppose I will have a similar feeling once I begin working in C#.
The most common complaint I hear (and I used to say also) about Java is its performance compared to compiled languages. I still feel this is a valid argument, but every day it loses some steam. Advances in JVMs have brought great speed increases, but the greatest improvement is the time spent in Java. Like most languages/CPUs/APIs, when there is a new widget on the market, it takes a while to learn about it and its intricacies. People used to (and still do to some extent) slam C++ for being a bloated, inefficient C. As time has marched on, this argument has lost it potency. The same holds true with Java. As developers learn the ins and outs of Java (like dont use Vector where you can use ArrayList), we will see Java gain more acceptance.
Nick Loadholtes
This is in regards to Table 1 on page 62 of the article by Andrew Koenig and Barbara E. Moo (C++ Made Easier: Which Container Should I Use?, CUJ, August 2001) about the STL sequential containers.
The table states that the space overhead for a deque is fixed per container. The table states that the space overhead for a vector is usually a constant multiple of the container size. Given even my limited exposure to implementation details for those containers, I believe those table entries are incorrect and should be reversed.
Could this belief either be confirmed or denied?
Brian F. Seaberg
I believe that the table is correct, but perhaps we dont have the same understanding about what it means.
Suppose c is an empty container, and we execute c.push_back(x) some number of times. The question is how much memory the container reserves for elements that might be appended to the container in the figure, but havent been yet.
For a vector, that answer is a multiple of the number of elements already in the vector. The multiple may be less than one, but its still a multiple. The reason is that each time the vector grows, it does so by allocating a multiple of the number of elements already in the container.
For a deque, the typical implementation is to use fixed-sized blocks. The wastage is therefore only the unused portion of the first and last block, which is bounded by a constant regardless of how many elements are in the container.
That is the sense in which we intended the table to be interpreted.
Regards,
Andrew Koenig
Cristian,
Theres an error in your article, Generalizing the Concepts Behind auto_ptr, (CUJ, August 2001) that I leave to you to generalize. Basically, the problem is that:
fclose(0);
crashes dont remember about Unix, but definitely on Win32.
Heres your code from pp.38-39 plus crashHere plus main that compiles (and explodes) under Microsoft Visual C++ 6.0:
// - crash_test.cpp #include <stdio.h> // your part: template<class H> struct handle_traits { static void dispose(H) throw(); static H null_value(); }; template<> void handle_traits<FILE*>::dispose (FILE* fp) throw() { fclose(fp); } template<> FILE* handle_traits<FILE*>::null_value() { return 0; }; template<class H, class T = handle_traits<H> > class auto_handle { public: explicit auto_handle (const H& h = T::null_value()) throw() : handle_(h) {} ~auto_handle() throw() { T::dispose(handle_); } H get() const throw() { return handle_; } private: H handle_; }; // my part: void crashHere() { // zeroed in ctor, fclosed in dtor ??? auto_handle<FILE*> hF; } void main() { crashHere(); } // end of crash_test.cpp
A safe destructor should be
template<> void handle_traits<FILE*>::dispose (FILE* fp) throw() { if(fp != handle_traits<FILE*>::null_value()) fclose(fp); }
Thanks for a very interesting article, anyway. The ref(42) trick is brilliant.
Alex Shvedov
Good catch, Alex!
Indeed, the safe (and correct) specialization for handle_traits<FILE*>::dispose needs to check for the null_value. This is a notable difference between auto_ptr and auto_handle. Since invoking delete on a null pointer has no effect, ~auto_ptr doesnt have to worry about checking for a null pointer.
I also checked on MSDN for DeleteObject and was happy to find out that my HBRUSH example is not plagued by the same bug. The deletion of the GDI object will just silently fail: If the specified handle is not valid or is currently selected into a DC, the return value is zero.
Just out of curiosity, I tried fclose(0) on Linux, where it crashes with a segmentation fault, and on a DEC machine running OSF/1 where it nicely returned a -1, and errno was set to EBADF (indicating that the file descriptor underlying the stream parameter is not valid).
I apologize for my email address missing from the bio info. (I thought I put it there, but it looks like for some reason it got omitted).
Thanks for your appreciation and for taking the time to bring the bug to my attention.
Cristian Vlasceanu