Fei Xue
Fei Xue

Reputation: 2045

what's the difference between the two code block?

In my program , I use basename function to get the partition. first , I write a if sentence like this:

if (!strncmp(buf, 
    basename("/dev/mmcblk0p3"), 
    strlen(basename("/dev/mmcblk0p3"))) {
    ret = 1;
} else {
    ret = 0;
}

buf point to string "mmcblk0p3" , but the ret = 0, using gdb, I found basename("/dev/mmcblk0p3") returned a weird string, but when i changed the program like this:

char *p = NULL;
p = basename("/dev/mmcblk0p3");
if (!strncmp(buf, p, strlen(p)) {
    ret = 1;
} else {
    ret = 0;
}

the ret is 1, the program runs normal. What is the difference? basename cannot be used like this ? Compiling environment is armel7v/gcc.

Upvotes: 2

Views: 103

Answers (2)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

One consequence of using a non-reentrant function basename that returns a string is that your subsequent invocations invalidate the prior results. You need to make a copy of the return value before making a second call, or stop using the old value after the second call has returned. This is because basename has only one internal buffer to store its result, assuming that it does not modify its parameter ( which looks to be the case with your program, because it does not crash on a string literal; still, it's undefined behavior).

Modify your program as follows to make it portable:

char *p = NULL;
char pathname[] = "/dev/mmcblk0p3";
p = basename(pathname);
if (!strncmp(buf, p, strlen(p)) {
    ret = 1;
} else {
    ret = 0;
}

Upvotes: 1

unwind
unwind

Reputation: 399723

The classical (POSIX) basename() function may modify its input string.

It seems your version is modifying the input, so the second call is not getting the same string as the first, making the above code very confusing.

Worse: you're also invoking undefined behavior by having basename() modify a string literal.

Upvotes: 3

Related Questions