缓冲区上的 basename 进入分段错误 [英] basename on buffer goes into segmentation fault

查看:71
本文介绍了缓冲区上的 basename 进入分段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在正在使用 basename 进行调整,但我遇到了一个非常奇怪的案例(至少对我而言).代码如下:

字符缓冲区[300];字符* p;strcpy(buffer, "../src/test/resources/constraints_0020_000");printf("%d\n", strcmp(basename("../src/test/resources/constraints_0020_000"), "constraints_0020_000"));//按预期工作printf("断言 testBasename02");printf("%d\n", strcmp(basename(buffer), "constraints_0020_000") == 0);printf("完成 1\n");//进入分段错误printf("%d\n", strcmp(basename(&buffer), "constraints_0020_000") == 0);printf("完成 2\n");//进入分段错误printf("%d\n", strcmp(basename(&buffer[0]), "constraints_0020_000") == 0);printf("完成 3\n");//进入分段错误p = malloc(strlen("../src/test/resources/constraints_0020_000") +1);strcpy(p, "../src/test/resources/constraints_0020_000");printf("%d\n", strcmp(basename(p), "constraints_0020_000") == 0);//按预期工作免费(p);printf("全部完成\n");

第一个 strcmp 完全正常工作;这是第二个让我困惑的问题:为什么缓冲区会出现分段错误?我试图以不同的方式对缓冲区进行编码,但结果是一样的.

我当然可以忍受这种行为,但是...如果我给他一个 const char*basename,我真的不明白有什么区别一个缓冲区(最后也是一个 char*).

是否有文件解释这种行为?只有我吗?我试图寻找解释,但找不到任何解释.

这里是我电脑的规格(如果你需要的话):

  • 操作系统:Ubuntu 16.4(64 位 Windows 10 64 位虚拟化);
  • CPU(不是我认为有用的):Intel® Core™ i5-3230M CPU @ 2.60GHz × 2;

解决方案

根据 手册页

<块引用>

错误

在这些函数的 POSIX 版本的 glibc 实现中,它们修改了它们的参数,并在使用像 "/usr/" 这样的静态字符串调用时出现段错误.[...]

基本上,

 basename("../src/test/resources/constraints_0020_000")

invokes 调用 未定义行为,因为这是试图修改字符串文字.><小时>

注意:如手册页中所述,需要更改单词.像阅读一样,

<块引用>

在这些函数的 POSIX 版本的 glibc 实现中,它们修改了它们的参数,并在使用像 "/usr/" 这样的静态字符串调用时调用未定义的行为代码>.[...]

分段错误是 UB 的副作用之一,但不是唯一的副作用.

FWIW,尝试修改字符串文字本身会调用 UB.引用 C11,章节 §6.4.5,字符串文字

<块引用>

[...] 如果程序试图修改这样的数组,行为是未定义.

<小时>

正如在后续评论中所讨论的,另一个问题是缺少头文件.你需要有

 #include 

添加以便获得函数 basename() 的前向声明.

I'm tweaking with basename right now and I encounter a case really weird (at least for me). Here's the code:

char buffer[300];
char* p;

strcpy(buffer, "../src/test/resources/constraints_0020_000");
printf("%d\n", strcmp(basename("../src/test/resources/constraints_0020_000"), "constraints_0020_000")); //works as expected
printf("assert testBasename02");
printf("%d\n", strcmp(basename(buffer), "constraints_0020_000") == 0);
printf("done 1\n"); //goes in segmentation fault
printf("%d\n", strcmp(basename(&buffer), "constraints_0020_000") == 0);
printf("done 2\n"); //goes in segmentation fault
printf("%d\n", strcmp(basename(&buffer[0]), "constraints_0020_000") == 0);
printf("done 3\n"); //goes in segmentation fault
p = malloc(strlen("../src/test/resources/constraints_0020_000") +1);
strcpy(p, "../src/test/resources/constraints_0020_000");
printf("%d\n", strcmp(basename(p), "constraints_0020_000") == 0); //works as expected
free(p);
printf("all done\n");

The first strcmp works totally as excepted; it is the second one that puzzles me: why a buffer would go in segmentation fault? I tried to code the buffer all in different ways but the result is the same.

I can of course live with this behaviour but... I don't really understand what is the difference for basename if i feed him a const char* or a buffer (that in the end is also a char*).

Is there a document that explain this behaviour? Is it just me? I tried to look for explanations but I couldn't find any.

Here the specification of my computer (if you need them):

  • OS system: Ubuntu 16.4 (64 bit virtualized on Windows 10 64-bit);
  • CPU (not that I think is useful): Intel® Core™ i5-3230M CPU @ 2.60GHz × 2;

解决方案

According to the man page,

Bugs

In the glibc implementation of the POSIX versions of these functions they modify their argument, and segfault when called with a static string like "/usr/". [...]

Basically,

 basename("../src/test/resources/constraints_0020_000")

invokes invokes undefined behavior as this is an attempt to modify the string literal.


Note: As mentioned in the man page, there's a change of words needed. Read it like,

In the glibc implementation of the POSIX versions of these functions they modify their argument, and invokes undefined behavior when called with a static string like "/usr/". [...]

A segmentation fault is one of the side effects of UB, but not the only one.

FWIW, attempt to modify a string literal itself invokes the UB. Quoting C11, chapter §6.4.5, String literals

[...] If the program attempts to modify such an array, the behavior is undefined.


EDIT:

As discussed in follow up comments, an additional problem was missing header file. You need to have

  #include <libgen.h>

added so as to get the forward declaration of the function basename() available.

这篇关于缓冲区上的 basename 进入分段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆