鱼C论坛

 找回密码
 立即注册
查看: 2691|回复: 10

[已解决]为什么我修改了strerror函数返回的字符串会coredump呢?

[复制链接]
发表于 2022-10-26 21:32:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main(int argc, char **argv) {
    FILE *fp;
    fp = fopen("file.txt", "r");
    if(fp == NULL) {
        char *str = strerror(errno);
        *str = '!';
        printf("Error: %s\n", strerror(errno));
    }
    return 0;
}

运行时提示:Segmentation fault (core dumped)
最佳答案
2022-10-26 22:14:12
jackz007 发表于 2022-10-26 22:06
我以为是他自己写的函数,我看因为没有传递字符数组进去,返回的字符串的根就应该是在函数内部 ...

是的
如果编译器支持的话,会把字符串常量放在只读存储区
如果操作系统支持的话,对只读存储区的写操作会被捕获到,而系统的默认处理程序会选择杀死这个进程
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-10-26 21:40:16 | 显示全部楼层

回帖奖励 +2 鱼币

       The strerror() function returns a pointer to a string that describes the error code passed in the argument errnum, possibly using the LC_MESSAGES part of the current locale to select the appropriate language.  (For  example,  if  errnum  is  EINVAL, the returned description will be "Invalid argument".)  This string must not be modified by the application, but may be modified by a subsequent call to strerror() or strerror_l().  No other library function, including perror(3), will modify this string.
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-26 21:40:53 | 显示全部楼层
strerror()函数返回一个指向字符串的指针,该字符串描述在参数errnum中传递的错误代码,可能使用当前语言环境的LC_MESSAGES部分来选择适当的语言。(例如,如果errnum是EINVAL,返回的描述将是“无效参数”。)此字符串不能由应用程序修改,但可以通过后续调用strerror()或strerror_l()进行修改。没有其他标准库函数,包括perror(3),将修改此字符串。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-26 21:41:36 | 显示全部楼层

回帖奖励 +2 鱼币

    char *str = strerror(errno);   
        这个函数返回的指针应该指向了函数 strerror(); 中属于局部变量的字符数组变量,当函数退出的时候,这个数组所占用的内存空间已经被系统释放,被用于其它需要,所以, 下一句
        *str = '!';
        可能写入了一个不允许写入的内存区域,所以,导致奔溃。
           
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-26 21:57:25 | 显示全部楼层
jackz007 发表于 2022-10-26 21:41
这个函数返回的指针应该指向了函数 strerror(); 中属于局部变量的字符数组变量,当函数退出的时 ...

返回的这个字符串不可能在局部数组里面
函数返回后这个字符串不可能被释放
要不然调用这个函数的意义何在?
sh-5.1$ cat main.c
#include <stdio.h>
#include <string.h>

const char *get_str(void) {
    char buff[] = "hello world!";
    const char *p = buff;
    return p;
}

void print(const char *str) {
    puts(str);
}

int main(void) {
    print(strerror(0));
    print(get_str());
    return 0;
}
sh-5.1$ gcc -g -Wall -o main main.c
sh-5.1$ ./main
Success
zU
sh-5.1$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-26 22:06:33 | 显示全部楼层
本帖最后由 jackz007 于 2022-10-26 22:07 编辑
人造人 发表于 2022-10-26 21:57
返回的这个字符串不可能在局部数组里面
函数返回后这个字符串不可能被释放
要不然调用这个函数的意义何 ...


        我以为是他自己写的函数,我看因为没有传递字符数组进去,返回的字符串的根就应该是在函数内部。
        如果这样说就对了,返回的是常量字符串,而常量字符串在程序内是绝对不可以修改的,如果修改,就会奔溃,以前有个鱼油要求通过调用一个无参函数,修改 main() 中一个字符串的时候就试过,那个就是一个常量字符串,根本不可能修改。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-26 22:11:23 | 显示全部楼层
本帖最后由 人造人 于 2022-10-26 22:15 编辑

可以想到,strerror这个函数就是返回了一个字符串常量
这个常量存储在只读存储区
如果操作系统支持的话,对只读存储区的写操作会被捕获到,而系统的默认处理程序会选择杀死这个进程
#include <stdio.h>
#include <string.h>

char *get_str(void) {
    return "hello world!";
}

void print(const char *str) {
    puts(str);
}

int main(void) {
    char *str = get_str();
    puts(str);
    *str = '0';
    return 0;
}
sh-5.1$ readelf -S main
There are 37 section headers, starting at offset 0x4a48:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000000318  00000318
       000000000000001c  0000000000000000   A       0     0     1
。。。
  [16] .rodata           PROGBITS         0000000000002000  00002000
       0000000000000011  0000000000000000   A       0     0     4
  [17] .eh_frame_hdr     PROGBITS         0000000000002014  00002014
       0000000000000034  0000000000000000   A       0     0     4
。。。
       00000000000001f2  0000000000000000           0     0     1
  [36] .shstrtab         STRTAB           0000000000000000  000048d2
       0000000000000176  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), l (large), p (processor specific)
sh-5.1$

sh-5.1$ xxd main
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
00000010: 0300 3e00 0100 0000 4010 0000 0000 0000  ..>.....@.......
00000020: 4000 0000 0000 0000 484a 0000 0000 0000  @.......HJ......
。。。
00001ff0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00002000: 0100 0200 6865 6c6c 6f20 776f 726c 6421  ....hello world!
00002010: 0000 0000 011b 033b 3000 0000 0500 0000  .......;0.......
00002020: 0cf0 ffff 6400 0000 2cf0 ffff 4c00 0000  ....d...,...L...

。。。
00005360: d248 0000 0000 0000 7601 0000 0000 0000  .H......v.......
00005370: 0000 0000 0000 0000 0100 0000 0000 0000  ................
00005380: 0000 0000 0000 0000                      ........
sh-5.1$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-26 22:14:12 | 显示全部楼层    本楼为最佳答案   
jackz007 发表于 2022-10-26 22:06
我以为是他自己写的函数,我看因为没有传递字符数组进去,返回的字符串的根就应该是在函数内部 ...

是的
如果编译器支持的话,会把字符串常量放在只读存储区
如果操作系统支持的话,对只读存储区的写操作会被捕获到,而系统的默认处理程序会选择杀死这个进程
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-26 22:18:33 | 显示全部楼层
人造人 发表于 2022-10-26 22:11
可以想到,strerror这个函数就是返回了一个字符串常量
这个常量存储在只读存储区
如果操作系统支持的话, ...

可以看到,"hello world!" 这个字符串就存放在 .rodata 段
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-26 22:47:09 | 显示全部楼层
人造人 发表于 2022-10-26 22:18
可以看到,"hello world!" 这个字符串就存放在 .rodata 段

ok
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-26 23:12:12 | 显示全部楼层
本帖最后由 桃花飞舞 于 2022-10-26 23:29 编辑

虽然能看懂答案,却没看懂问题,从楼上的答案隐约感觉是这句导致的错误*str = '!'; core dumped通常在linux的内核中会出现
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-26 22:58

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表