pointer being freed was not allocated (osx only)
Question
The function below basically emulates mkdir -p
, recursively creating directories for a given path. With Linux I have no issues, however running under OSX it always segfaults with the error pointer being freed was not allocated
during the call to free(dir)
. Can anyone spot an error? When I step through execution in gdb I don't see any obvious problems, dir
is populated and the directory structure is created without error.
static int
mkpath(const char *path)
{
int result = 0;
struct stat st;
char *p = NULL, *dir = strdup(path);
char *tmp = g_malloc0(sizeof(char) * strlen(cache.path) + strlen(dir) + 1);
dir = dirname(dir);
tmp = strcpy(tmp, cache.path);
p = strtok(dir, "/");
while(p != NULL) {
tmp = strncat(tmp, "/", 1);
tmp = strncat(tmp, p, strlen(p));
if(stat(tmp, &st) == 0) {
if(S_ISDIR(st.st_mode)) {
p = strtok(NULL, "/");
continue;
}
result = -ENOTDIR;
break;
}
if(mkdir(tmp, S_IRWXU) == -1) {
result = -errno;
break;
}
p = strtok(NULL, "/");
}
free(tmp);
free(dir);
return result;
}
Solution
Take a look at the man page for dirname: http://linux.die.net/man/3/dirname. "Both dirname() and basename() return pointers to null-terminated strings. (Do not pass these pointers to free(3).)" Also, you should probably not being doing dir = dirname(dir) as you've then lost the pointer to the memory allocated by strdup (strdup allocated memory should be passed to free).
OTHER TIPS
The man page for dirname
says that you should not pass the return value to free()
. Yet that is exactly what you are doing.
according to the man page:
WARNINGS The dirname() function returns a pointer to internal static storage space that will be overwritten by subsequent calls (each function has its own separate storage).
so you probably don't want to be freeing it. i'm guessing that's different on linux?