2

在我的程序中,我使用 basename 函数来获取分区。首先,我写一个这样的 if 语句:

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

buf 指向字符串 "mmcblk0p3" ,但是 ret = 0,使用 gdb,我发现 basename("/dev/mmcblk0p3") 返回了一个奇怪的字符串,但是当我像这样更改程序时:

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

ret 为 1,程序运行正常。有什么区别?basename 不能这样使用?编译环境是armel7v/gcc。

4

2 回答 2

3

经典 (POSIX)basename()函数可以修改其输入字符串。

看来您的版本正在修改输入,所以第二次调用没有得到与第一次相同的字符串,使上面的代码非常混乱。

更糟糕的是:您还通过basename()修改字符串文字来调用未定义的行为。

于 2013-05-21T08:48:39.130 回答
1

使用返回字符串的不可重入函数 basename 的一个后果是您的后续调用会使先前的结果无效。您需要在进行第二次调用之前复制返回值,或者在第二次调用返回后停止使用旧值。这是因为 basename 只有一个内部缓冲区来存储其结果,假设它不修改其参数(您的程序看起来就是这种情况,因为它不会在字符串文字上崩溃;仍然是未定义的行为)。

如下修改您的程序以使其可移植:

char *p = NULL;
char pathname[] = "/dev/mmcblk0p3";
p = basename(pathname);
if (!strncmp(buf, p, strlen(p)) {
    ret = 1;
} else {
    ret = 0;
}
于 2013-05-21T09:03:02.860 回答