An Rvalue Reference Issue
By chys on November 13th, 2009I’m now convinced it was way too premature to try to take advantage of C++0x features (r-value references, etc.) in tiary (if the compiler supports).
With GCC 4.3.4, even the following innocent function leads to segmentation fault:
#include <string>
#include <utility>
std::string && my_move (std::string &str)
{
std::string && tmp = std::move (str);
return tmp;
}
In GCC 4.4, this function simply casts the non-const lvalue-reference parameter to an r-value reference and returns it, which I think is correct. In 4.3, however, tmp refers to a temporary object on stack, move-constructed from str.
Then I replaced std::string with std::list<int> and tried again. This time, GCC (4.3.4) itself segfaults. Ooops..
DHCPNAK
By chys on November 3rd, 2009The following is extracted from my system log file:
Nov 1 11:53:24 laptop dhclient: DHCPREQUEST on eth0 to 255.255.255.255 port 67
Nov 1 11:53:24 laptop dhclient: DHCPNAK from 192.168.1.1
Nov 1 11:53:25 laptop dhclient: DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 8
Nov 1 11:53:25 laptop dhclient: DHCPOFFER from 192.168.1.1
Nov 1 11:53:25 laptop dhclient: DHCPREQUEST on eth0 to 255.255.255.255 port 67
Nov 1 11:53:25 laptop dhclient: DHCPACK from 192.168.1.1
Nov 1 11:53:25 laptop dhclient: bound to 192.168.1.3 — renewal in 39303 seconds.
Apparently, my computer tried to renew the IP address from the router, and was rejected. Then my computer started over a new DHCP request, and was offered the same IP.
I found all renewal requests were denied after checking the logs back a few days. I wonder if the router was designed to deny any DHCPREQUEST unless it immediately follows a DHCPOFFER. I can’t figure out any good reason for this. What I could think of is that the firmware programmers were just too lazy to implement a good DHCP server – after all, it was the cheapest wireless router I was able to find…
A Python sort trick
By chys on October 23rd, 2009>>> a = [12,14,133,130,176,25,54,79,127] >>> b = sorted(range(len(a)),key=a.__getitem__) >>> b [0, 1, 5, 6, 7, 8, 3, 2, 4] >>> map(a.__getitem__,b) [12, 14, 25, 54, 79, 127, 130, 133, 176]
b is the so called sort index.
Reference
http://www.newsmth.net/bbscon.php?bid=284&id=59819
Tags: Python
std::hash<std::string>
By chys on October 4th, 2009TR1 requires std::tr1::hash (std::hash in C++0x) to be instantiable for integer/floating point types, std::string and std::wstring. (C++0x added std::error_code, std::thread:id, std::bitset, std::u16string, std::u32string, and std::vector<bool>.)
But for strings, every call to std::hash<string>::operator()(std::string) incurs an unnecessary copy construction, which can be expensive in implementations where std::basic_string does not use COW.
Developers of GCC are apparently aware of this, and they added specializations std::hash<const std::string &> and std::hash<const std::wstring &> starting from GCC 4.3.
However, I still guess we cannot easily benefit from this since we will need to write something like this:
std::unordered_set<std::string, std::hash<const std::string &>>
(In C++0x it’s no longer required to insert a space between the two larger-than characters.)
Too ugly and inconvenient to use, unless our program is really time critical.
Reduce the delay after ESC in ncurses
By chys on September 26th, 2009In ncurses-based programs, the default delay after the ESC key is way too long. (Such a delay is necessary to differentiate the ESC key from function keys.)
There seems to be no such delay in VIM. But with strace, we can find that VIM actually delays, but for only 25 milliseconds, shorter than 100ms – the minimal time interval that human can perceive:
read(0, "\33"..., 4096) = 1
select(6, [0 3 5], NULL, [0 3], {0, 0}) = 0 (Timeout)
gettimeofday({1253979790, 537775}, NULL) = 0
select(6, [0 3 5], NULL, [0 3], {0, 25000}) = 0 (Timeout)
If 25ms works reliably for VIM, so should it do for other programs. There seems to be no functions setting this interval in ncurses, but we can directly modify the global variable ESCDELAY. Ncurses also accepts the environment variable also named ESCDELAY, so we may also want to honor the user’s choice:
if (getenv ("ESCDELAY") == NULL)
ESCDELAY = 25;
Not confident in its portability, I detect this undocumented (it seems) feature with cmake in tiary (my project).
Update (Feb. 22, 2010): It’s preferable to use the function set_escdelay.
Ack is a good alternative to grep
By chys on September 6th, 2009When I grep -r something in a Subversion-controlled directory, I get a lot of results under the .svn.
In this sense, Git is better than Subversion. (Git creates only one .git directory, and stores data in some compressed format which gets ignored by grep -r.)
So I have switched to ack when working with Subversion. Ack is written in Perl, claimed to be “aimed at programmers with large trees of heterogeneous source code.”
To Risk Life or Job
By chys on August 25th, 2009From my[confined]space
A comment says:
On the other hand, if you make your code confusing as hell, you will have much better job security.
I have been assuming some maniac serial killer would be maintaining it while doing my recent (private, but to be public) project, but still find my own codes could be confusing.
Anyway, I am glad that this did not happen until it reached about 70 files and 8,000 lines – the threshold used to be 2 files and 300 lines. The project now has about 110 files and 14,000 lines.
__cmp__ should be reintroduced to Python
By chys on August 11th, 2009A lot of people think this decision to drop __cmp__ from Python sucks. (1 2)
The cmp argument is also dropped from list.sort and sorted. Some people explain that some programmers used to use cmp when it is more convenient and efficient to use key. By dropping cmp, poor programmers are forced to use key. On the other hand, almost all comparators found in practice are actually based on some kind of key function.
Well, theoretically this probably is true: something.sort(key=locale.strxfrm) is better than something.sort(cmp=locale.strcoll).
BUT, what can I do if I only have a third-party comparator?
I have a Python script where I use vercmp, provided in the source of Gentoo Portage, to sort a list of Gentoo packages. No corresponding verkey is provided. So now, in Python 3, I have to either write a verkey myself, or use the following ugly and inefficient workaround:
class VerKey:
def __init__(self,str):
self.str = str
def __lt__(self,other):
return vercmp(self.str, other.str) < 0
versions.sort (key = VerKey)
Tags: Python
null pointer to member
By chys on July 19th, 2009The most straightforward implementation of a pointer to member is to store the offset:
struct Struct
{
int a;
int b;
};
The internal value of &Struct::a is 0 and &Struct::b is sizeof(int).
This leads to the illusion that &Struct::a, a valid pointer, is equal to a null pointer. Not only does this violate the standard, but also breaks many codes existing in practice.
The current (pre-0x) orthodox method of defining a cast from user-defined class to bool is not using operator bool (which leads to some unwanted consequences), but something like this:
class MyClass
{
/* ....... */
struct BooleanConvert { int val; };
operator int BooleanConvert::* () const
{
return ( /* true */ ) ? &BooleanConvert::val : 0;
}
};
It is hard to read, but the idea is simple: return a valid pointer (to member) if true, a null pointer (to member) if false.
Q: It seems both pointers evaluate to 0. How do they distinguish them?
A: In practice, a null pointer to member is represented, internally, by a value of -1 instead of 0!
So,
#include <cstdio>
#include <cstddef>
using namespace std;
struct Struct
{
int a;
};
int main()
{
union
{
int Struct::*ptr;
void * val;
};
ptr = 0;
printf ("%p\n", val);
}
the above program would output 0xffffffff (32-bit systems).
Fortunately, this does not annoy. We can safely ignore this detail (except when writing a compiler, of coz..) It seems that, except using unions or brutal memory access, there is no way to convert pointers to member to/from integers and normal pointers. (C-style casts, reinterpret_cast, etc. all reject such conversions.)
Tags: C/C++
I can’t PGO compile Firefox
By chys on July 17th, 2009A normal build of Firefox for Linux is reportedly even slower than the Win32 binary running under Wine.
The reason is reportedly that the pre-compiled binary for Windows uses PGO (profile guided optimization), which is usually not enabled under Linux. Sure, the fact that GCC does not generate as efficient codes as VC may also be a reason.[1]
Firefox also supports PGO in Linux. However, I failed at this (3.5.1). The profile-generating binary always segfaults.
Other people have encountered the same problem, even with the official PKGBUILD from Arch Linux. It is said to be a compiler problem.
Well, gave up. Maybe I’ll try it again some time later, with a more “stable” version of GCC probably.
[1] This statement only applies to the 32-bit platform. It seems GCC does a very good job on x86-64.
Profile-guided optimization is a relatively new feature. GCC began supporting it starting version 4.0; Microsoft VC 2005; and Intel C/C++/Fortran 9 (?).
A typical PGO-enabled building requires three steps:
(1) Build a profile-generating binary;
(2) Run the binary, which automatically collects useful data – branch probability, etc.
(3) Rebuild the program, using the data (“profile”) from Step 2.
With PGO, Internet Explorer reportedly gains an improvement of 8%, and Firefox 11% in JavaScript.
Tags: browser, dev, GCC, Linux, optimization

