两个代码块之间有什么区别?

时间:2013-05-21 08:44:31

标签: c

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

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。

2 个答案:

答案 0 :(得分:3)

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

似乎您的版本正在修改输入,因此第二次调用没有获得与第一次相同的字符串,使上述代码非常混乱。

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

答案 1 :(得分:1)

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

按如下方式修改程序以使其可移植:

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