If you compile an executable with -mmacosx-version-min=10.4 that calls QDir::canonicalName with specific paths, incorrect results are returned and the following error is printed to stderr:
malloc: *** error for object 0xbfffe280: pointer being freed was not allocated
- set a breakpoint in malloc_error_break to debug
There are a few conditions:
1) The path specified must not exist. However, the parent directory of the path must exist. For example, /Applications/foo must not exist, but /Applications must exist.
2) The Qt library must be compiled with -mmacosx-version-min=10.4. If it is compiled with -mmacosx-version-min=10.5 or greater, the bug will not occur. However, 10.4 is the default.
3) The running OS must be 10.6 or greater.
Since the path does not exist, most implementations of realpath should return NULL. However, legacy realpath does not return NULL in this case. It also apparently does not return a pointer to memory allocated with malloc, so attempting to free it causes the error shown above.
Looking further into this, the problem is that on Mac OSX there are many versions of realpath that could get called.
- In 10.4, realpath does not support the realpath(X,0) form that requires the caller to free the result. Also, the last component of the path does not need to exist.
- In 10.5, realpath does not support the realpath(X,0) form, but all components of the path need to exist.
- In 10.6, realpath supports the realpath(X,0) form, and all components of the path need to exist.
However, the -mmacosx-version-min flag causes strange behavior. In the documentation this is referred to as legacy mode.
- Running on 10.4 or 10.5, Qt correctly avoids using realpath since it will not support realpath(X,0).
- Running on 10.6 or greater, if the flag is set to 10.4, legacy mode is engaged. Legacy realpath does support the realpath(X,0) form that requires the caller to free the result. However, the last component of the path still does not need to exist. This is where this bug occurs.
- Running on 10.6 or greater, if the flag is set to 10.5 or greater, legacy mode is disabled. realpath does support the realpath(X,0) form that requires the caller to free the result, and the last component of the path must exist.
The simplest fix would be to always malloc the memory and avoid using the realpath(X,0) form. This avoids the malloc error in all cases. Depending on desired behavior, it may be worthwhile also checking if the path exists before calling realpath to be able to return proper information, but since in theory the file could be deleted by another process at the same time, I don't know if that's important.