Linux下core文件产生的一些注意问题

2023-05-16

              前面转载了一篇文章关于core文件的产生和调试使用的设置,但在使用有一些需要注意的问题,如 在什么情况 才会正确地产生core文件。

      列出一些常见问题:

一,如何使用core文件

1. 使用core文件

在core文件所在目录下键入:

gdb -c core

它会启动GNU的调试器,来调试core文件,并且会显示生成此core文件的程序名,中止此程序的信号等等。

如果你已经知道是由什么程序生成此core文件的,比如MyServer崩溃了生成core.12345,那么用此指令调试:

gdb -c core MyServer

以下怎么办就该去学习gdb的使用了


2. 一个小方法来测试产生core文件

直接输入指令:kill -s SIGSEGV $$


二,程序产生core的原因

造成程序coredump的原因很多,这里根据以往的经验总结一下:

1 内存访问越界
  a) 由于使用错误的下标,导致数组访问越界
  b) 搜索字符串时,依靠字符串结束符来判断字符串是否结束,但是字符串没有正常的使用结束符
  c) 使用strcpy, strcat, sprintf, strcmp, strcasecmp等字符串操作函数,将目标字符串读/写爆。应该使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函数防止读写越界。
 
2 多线程程序使用了线程不安全的函数。
应该使用下面这些可重入的函数,尤其注意红色标示出来的函数,它们很容易被用错:
asctime_r(3c) gethostbyname_r(3n) getservbyname_r(3n) ctermid_r(3s) gethostent_r(3n) getservbyport_r(3n) ctime_r(3c) getlogin_r(3c) getservent_r(3n) fgetgrent_r(3c) getnetbyaddr_r(3n) getspent_r(3c) fgetpwent_r(3c) getnetbyname_r(3n) getspnam_r(3c) fgetspent_r(3c) getnetent_r(3n) gmtime_r(3c) gamma_r(3m) getnetgrent_r(3n) lgamma_r(3m) getauclassent_r(3) getprotobyname_r(3n) localtime_r(3c) getauclassnam_r(3) etprotobynumber_r(3n) nis_sperror_r(3n) getauevent_r(3) getprotoent_r(3n) rand_r(3c) getauevnam_r(3) getpwent_r(3c) readdir_r(3c) getauevnum_r(3) getpwnam_r(3c) strtok_r(3c) getgrent_r(3c) getpwuid_r(3c) tmpnam_r(3s) getgrgid_r(3c) getrpcbyname_r(3n) ttyname_r(3c) getgrnam_r(3c) getrpcbynumber_r(3n) gethostbyaddr_r(3n) getrpcent_r(3n)
 
3 多线程读写的数据未加锁保护。
对于会被多个线程同时访问的全局数据,应该注意加锁保护,否则很容易造成core dump
 
4 非法指针
  a) 使用空指针
  b) 随意使用指针转换。一个指向一段内存的指针,除非确定这段内存原先就分配为某种结构或类型,或者这种结构或类型的数组,否则不要将它转换为这种结构或类型的指针,而应该将这段内存拷贝到一个这种结构或类型中,再访问这个结构或类型。这是因为如果这段内存的开始地址不是按照这种结构或类型对齐的,那么访问它时就很容易因为bus error而core dump.
 
5 堆栈溢出
不要使用大的局部变量(因为局部变量都分配在栈上),这样容易造成堆栈溢出,破坏系统的栈和堆结构,导致出现莫名其妙的错误。


三,注意的问题

 

在Linux下要保证程序崩溃时生成Coredump要注意这些问题:

 

  一、要保证存放Coredump的目录存在且进程对该目录有写权限。存放Coredump的目录即进程的当前目录,一般就是当初发出命令启动该进程时所在的目录。但如果是通过脚本启动,则脚本可能会修改当前目录,这时进程真正的当前目录就会与当初执行脚本所在目录不同。这时可以查看”/proc/<进程pid>/cwd“符号链接的目标来确定进程真正的当前目录地址。通过系统服务启动的进程也可通过这一方法查看。

 

  二、若程序调用了seteuid()/setegid()改变了进程的有效用户或组,则在默认情况下系统不会为这些进程生成Coredump。很多服务程序都会调用seteuid(),如MySQL,不论你用什么用户运行mysqld_safe启动MySQL,mysqld进行的有效用户始终是msyql用户。如果你当初是以用户A运行了某个程序,但在ps里看到的这个程序的用户却是B的话,那么这些进程就是调用了seteuid了。为了能够让这些进程生成core dump,需要将/proc/sys/fs /suid_dumpable文件的内容改为1(一般默认是0)。

 

  三、要设置足够大的Core文件大小限制了。程序崩溃时生成的Core文件大小即为程序运行时占用的内存大小。但程序崩溃时的行为不可按平常时的行为来估计,比如缓冲区溢出等错误可能导致堆栈被破坏,因此经常会出现某个变量的值被修改成乱七八糟的,然后程序用这个大小去申请内存就可能导致程序比平常时多占用很多内存。因此无论程序正常运行时占用的内存多么少,要保证生成Core文件还是将大小限制设为unlimited为好。

            在shell里使用命令:ulimit -c unlimited,这样进行修改只是对本次会话有效,是临时的,如果想让修改永久生效,则需要修改配置文件,如 .bash_profile/etc/profile/etc/security/limits.conf

    如下:

    [root@otctest ~]# vim  /etc/profile

    结果如图:

     
 

    把红框里的行注释,并新加入一行:

    ulimit -c unlimited

    保存,退出即可。


四,产生core文件的时机

     当我们的程序崩溃时,内核有可能把该程序当前内存映射到core文件里,方便程序员找到程序出现问题的地方。最常出现的,几乎所有C程序员都出现过的错误就是“段错误”了。也是最难查出问题原因的一个错误。下面我们就针对“段错误”来分析core文件的产生、以及我们如何利用core文件找到出现崩溃的地方。

何谓core文件

当一个程序崩溃时,在进程当前工作目录的core文件中复制了该进程的存储图像。core文件仅仅是一个内存映象(同时加上调试信息),主要是用来调试的。

当程序接收到以下UNIX信号会产生core文件:

名字

说明

ANSI C  POSIX.1

SVR4  4.3+BSD

缺省动作

SIGABRT

异常终止(abort)

  .       .

  .      .

终止w/core

SIGBUS

硬件故障

          .

  .      .

终止w/core

SIGEMT

硬件故障

 

  .      .

终止w/core

SIGFPE

算术异常

  .       .

  .      .

终止w/core

SIGILL

非法硬件指令

  .       .

  .      .

终止w/core

SIGIOT

硬件故障

 

  .      .

终止w/core

SIGQUIT

终端退出符

          .

  .      .

终止w/core

SIGSEGV

无效存储访问

  .       .

  .      .

终止w/core

SIGSYS

无效系统调用

 

  .      .

终止w/core

SIGTRAP

硬件故障

 

  .      .

终止w/core

SIGXCPU

超过CPU限制(setrlimit)

 

  .      .

终止w/core

SIGXFSZ

超过文件长度限制(setrlimit)

 

  .      .

终止w/core

在系统默认动作列,“终止w/core”表示在进程当前工作目录的core文件中复制了该进程的存储图像(该文件名为core,由此可以看出这种功能很久之前就是UNIX功能的一部分)。大多数UNIX调试程序都使用core文件以检查进程在终止时的状态。

core文件的产生不是POSIX.1所属部分,而是很多UNIX版本的实现特征。UNIX第6版没有检查条件(a)和(b),并且其源代码中包含如下说明:“如果你正在找寻保护信号,那么当设置-用户-ID命令执行时,将可能产生大量的这种信号”。4.3 + BSD产生名为core.prog的文件,其中prog是被执行的程序名的前1 6个字符。它对core文件给予了某种标识,所以是一种改进特征。

表中“硬件故障”对应于实现定义的硬件故障。这些名字中有很多取自UNIX早先在DP-11上的实现。请查看你所使用的系统的手册,以确切地确定这些信号对应于哪些错误类型。

下面比较详细地说明这些信号。

• SIGABRT 调用abort函数时产生此信号。进程异常终止。

• SIGBUS  指示一个实现定义的硬件故障。

• SIGEMT  指示一个实现定义的硬件故障。

EMT这一名字来自PDP-11的emulator trap 指令。

• SIGFPE  此信号表示一个算术运算异常,例如除以0,浮点溢出等。

• SIGILL  此信号指示进程已执行一条非法硬件指令。

4.3BSD由abort函数产生此信号。SIGABRT现在被用于此。

• SIGIOT  这指示一个实现定义的硬件故障。

IOT这个名字来自于PDP-11对于输入/输出TRAP(input/output TRAP)指令的缩写。系统V的早期版本,由abort函数产生此信号。SIGABRT现在被用于此。

• SIGQUIT 当用户在终端上按退出键(一般采用Ctrl-/)时,产生此信号,并送至前台进

程组中的所有进程。此信号不仅终止前台进程组(如SIGINT所做的那样),同时产生一个core文件。

• SIGSEGV 指示进程进行了一次无效的存储访问。

名字SEGV表示“段违例(segmentation violation)”。

• SIGSYS  指示一个无效的系统调用。由于某种未知原因,进程执行了一条系统调用指令,

但其指示系统调用类型的参数却是无效的。

• SIGTRAP 指示一个实现定义的硬件故障。

此信号名来自于PDP-11的TRAP指令。

• SIGXCPU SVR4和4.3+BSD支持资源限制的概念。如果进程超过了其软C P U时间限制,则产生此信号。

• SIGXFSZ 如果进程超过了其软文件长度限制,则SVR4和4.3+BSD产生此信号。

摘自《UNIX环境高级编程》第10章 信号。

 

使用core文件调试程序

看下面的例子:

/*core_dump_test.c*/
 #include <stdio.h>
const char *str = "test";
void core_test(){
    str[1] = 'T';
}

int main(){
    core_test();
    return 0;
}

编译:
gcc –g core_dump_test.c -o core_dump_test

如果需要调试程序的话,使用gcc编译时加上-g选项,这样调试core文件的时候比较容易找到错误的地方。

执行:
 ./core_dump_test
段错误

运行core_dump_test程序出现了“段错误”,但没有产生core文件。这是因为系统默认core文件的大小为0,所以没有创建。可以用ulimit命令查看和修改core文件的大小。
ulimit -c 0
ulimit -c 1000
ulimit -c 1000

-c 指定修改core文件的大小,1000指定了core文件大小。也可以对core文件的大小不做限制,如:

ulimit -c unlimited
ulimit -c unlimited

如果想让修改永久生效,则需要修改配置文件,如 .bash_profile、/etc/profile或/etc/security/limits.conf。

再次执行:
./core_dump_test
段错误 (core dumped)
ls core.*
core.6133

可以看到已经创建了一个core.6133的文件.6133是core_dump_test程序运行的进程ID。

调式core文件
core文件是个二进制文件,需要用相应的工具来分析程序崩溃时的内存映像。

file core.6133

core.6133: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from 'core_dump_test'

在Linux下可以用GDB来调试core文件。

gdb core_dump_test core.6133

GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
Core was generated by `./core_dump_test'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/tls/libc.so.6...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0  0x080482fd in core_test () at core_dump_test.c:7
7           str[1] = 'T';
(gdb) where
#0  0x080482fd in core_test () at core_dump_test.c:7
#1  0x08048317 in main () at core_dump_test.c:12
#2  0x42015574 in __libc_start_main () from /lib/tls/libc.so.6

GDB中键入where,就会看到程序崩溃时堆栈信息(当前函数之前的所有已调用函数的列表(包括当前函数),gdb只显示最近几个),我们很容易找到我们的程序在最后崩溃的时候调用了core_dump_test.c 第7行的代码,导致程序崩溃。注意:在编译程序的时候要加入选项-g。您也可以试试其他命令, 如 fram、list等。更详细的用法,请查阅GDB文档。

core文件创建在什么位置

在进程当前工作目录的下创建。通常与程序在相同的路径下。但如果程序中调用了chdir函数,则有可能改变了当前工作目录。这时core文件创建在chdir指定的路径下。有好多程序崩溃了,我们却找不到core文件放在什么位置。和chdir函数就有关系。当然程序崩溃了不一定都产生core文件。

什么时候不产生core文件

在下列条件下不产生core文件:
( a )进程是设置-用户-ID,而且当前用户并非程序文件的所有者;
( b )进程是设置-组-ID,而且当前用户并非该程序文件的组所有者;
( c )用户没有写当前工作目录的许可权;
( d )文件太大。core文件的许可权(假定该文件在此之前并不存在)通常是用户读/写,组读和其他读。

利用GDB调试core文件,当遇到程序崩溃时我们不再束手无策。





本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux下core文件产生的一些注意问题 的相关文章

  • Node exec 无权执行脚本

    直到最近 它都运行良好 但是当我今天尝试使用它时 它无法正常运行 它返回以下错误 错误 命令失败 bin sh c home pi RPi Computer Power RPi Server routes scripts hash js 1
  • vm.dirty_ratio 和 vm.dirty_background_ratio 之间的区别?

    我目前正在试验中找到的内核参数 proc sys vm 尤其dirty ratio and dirty background ratio 内核文档对两者都有以下解释 脏背景比例 包含 以包含空闲页面的总可用内存的百分比表示 和可回收页 后台
  • 在 Linux 中使用仅限 CLI 的工具生成磁盘使用情况图/图表

    在这个问题中 https stackoverflow com questions 32230 tracking down where disk space has gone on linux有人询问如何在 Linux 中显示磁盘使用情况 我
  • 如何在 Linux 上调用 Python 中的内联机器代码?

    我正在尝试从 Linux 上的纯 Python 代码调用内联机器代码 为此 我将代码嵌入到字节文字中 code b x55 x89 xe5 x5d xc3 然后打电话mprotect http www kernel org doc man
  • 每个进程是否都存在内核堆栈?

    每个用户空间进程是否都存在一个内核堆栈和一个用户空间堆栈 如果两个堆栈都存在 那么每个用户空间进程应该有 2 个堆栈指针 对吗 在 Linux 中 每个任务 用户空间或内核线程 都有一个 8kb 或 4kb 的内核堆栈 具体取决于内核配置
  • 安全地记住 bash 脚本中的 ssh 凭据[重复]

    这个问题在这里已经有答案了 假设我有一个 bash 脚本 它通过 ssh 在远程计算机上执行命令 Do something here ssh otheruser host command1 Do something else ssh oth
  • 使用openssl从服务器获取证书

    我正在尝试获取远程服务器的证书 然后可以将其添加到我的密钥库中并在我的 Java 应用程序中使用 一位高级开发人员 正在度假 告诉我我可以运行这个 openssl s client connect host host 9999 获取转储的原
  • 远程 ssh 命令:第一个回显输出丢失

    我试图通过 ssh 1 liner 调用在远程机器上运行多个命令 方法是将它们指定为传递给 bash c 的分号分隔字符串 它适用于某些情况 但不适用于其他情况 看一下这个 Note the echo 1 output is lost ba
  • 在linux x86平台上学习ARM所需的工具[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有一个 x86 linux 机器 在阅读一些关于 ARM 的各种信息时 我很好奇 现在我想花一些时间学
  • Linux 的 gcc __attribute__((selectany)) 替代方案?

    我想知道是否有替代方案 attribute selectany 在Linux中 我想定义这样的东西 char a qwe zxc 并将其包含在许多链接在一起的 c 文件中 因此链接器将看到 a 的多个定义 因此不会链接 我读过这个属性 se
  • 模拟用户输入以使用不同参数多次调用脚本

    我必须使用提供的脚本 该脚本在脚本运行时接受用户输入而不是参数 我无法解决这个问题 脚本的一个例子是 bin bash echo param one read one doSomething echo param two read two
  • 使用 WGET 运行 cronjob PHP

    我尝试执行一个 cron 并每 5 分钟运行一个 url 我尝试使用 WGET 但我不想下载服务器上的文件 我只想运行它 这是我使用的 crontab 5 wget http www example com cronit php 除了 wg
  • 从命名管道读取

    我必须实现一个 打印服务器 我有 1 个客户端文件和 1 个服务器文件 include
  • 使用 gatttool 或 bluepy BLE 订阅通知

    我正在使用 bluepy 编写一个程序 用于监听蓝牙设备发送的特征 我还可以使用任何库或语言 唯一的限制是在 Linux 上运行 而不是在移动环境中运行 似乎仅在移动设备中广泛使用 没有人在桌面上使用 BLE 使用 bluepy 我注册了委
  • 如何从 C 文件更改终端中的目录

    如何从 C 程序更改将在终端上生效的目录 实际上不要告诉 system 函数或 chdir 函数 这些仅适用于 C 中的进程或子 shell 假设我正在从 bash shell 执行一个 C 程序 其进程 ID 为 10223 那么 我可以
  • 如何真正释放 Linux 中的大页面以供新进程使用?

    真的找不到太多关于此的信息 希望有人可以提供帮助 我正在假脱机使用 100GB java 堆作为大数据缓存 为了避免与文件系统缓存等内容发生冲突 并且因为它通常性能更好 我将其分配在大页面中 我保留了 51 200 x 2MB 大页面 一切
  • 如何使用 tmuxinator 在 tmux 中拆分水平窗格内的两个垂直窗格

    目前我的 tmuxinator yml 文件中有这个 windows editor layout main horizontal panes vim server rails s 这给了我两个窗口 一个用于编辑器 另一个用于服务器 在编辑器
  • bash双括号问题

    我对 bash 脚本非常陌生 在使用双括号时遇到了问题 我似乎无法让它们在 Ubuntu Server 11 10 中工作 我的下面的脚本位于 if test sh 中 bin bash if 14 14 then echo FOO fi
  • 在64位操作系统上以32位模式和64位模式编译ioctl函数的执行有什么不同?

    我有 64 位 Enterprise SuSE 11 我有一个应用程序 它打开 HIDRAW 设备并在其上操作 ioctl 函数以从该设备获取原始信息 如下所示 struct hidraw devinfo devinfo int fd op
  • 从 Linux 命令行发送 SNMP 陷阱消息

    Folks 我需要从 Linux 命令行使用此命令 snmptrap 将自定义消息发送到陷阱侦听器 我需要根据用户设置在 v1 和 v2c 中发送相同的消息 这是我发现的 For v1 snmptrap v 1 c Tas hostname

随机推荐

  • Ajax请求返回图片

    需求 xff1a 使用Ajax返回图片数据展示在Img标签上 前端Ajax请求 lt HTML标签 gt lt img id 61 34 ImagePic 34 alt 61 34 Base64 encoded image 34 width
  • 多读书,读好书

    古人云读书百变其义自现 xff0c 当今是个大数据时代 xff0c 各类书籍种类繁多 xff0c 我们不可能一一预览 xff0c 同时也不需要 也没时间一一细看 xff0c 我们需要的是多遍阅读经典书籍 xff0c 将会事半功倍 下面我将介
  • kendoGrid合并单元格

    kendoGrid默认API中并没有合并单元格的方法 xff0c 故自己借鉴网友的代码并做了改造 xff0c 下述代码及完成了kendoGrid中的行的合并 xff08 在 dataBound事件中完成 xff09 span class t
  • Git合并指定文件到其他分支

    1 合并某个分支上的指定commit span class token comment 在dev分支合并bugfix分支上的 ac0ca63 commit span git branch span class token operator
  • 有刷电机与无刷电机的区别,就是这么简单明了:

    一 有刷电机 xff1a 有刷电机是大家最早接触的一类电机 xff0c 例如很多电动小玩具 xff0c 或者很多家用的吹风机里面的电机都是有刷电机 有刷电机的主要结构就是定子 转子 电刷 xff0c 通过旋转磁场获得转动力矩 xff0c 从
  • ubuntu 完全干净的卸载docker

    1 删除某软件 及其安装时自动安装的所有包 sudo apt get autoremove docker docker ce docker engine docker io containerd runc 2 删除docker其他没有没有卸
  • shell命令—find

    find命令 span class token comment 删除 home fengshuiyue目录下一周前的目录 span fengshuiyue 64 ralc span class token operator gt span
  • shell命令—date

    date命令 span class token comment 获取当前时间 日期格式是 YYYY mm dd HH MM SS span span class token function date span span class tok
  • 大华硬盘录像机、网络摄像机、 网络硬盘录像机外网远程设置DDNS方法

    1 为了便于解释在下文介绍中 xff0c 硬盘录像机 网络摄像机 网络硬盘录像机统一称为 大华设备 2 外网最好是电信 如果不是 xff0c 那必须要确认客户的外网 IP 是唯一的 xff0c 不是与其他用户共用的 3 首先确保 大华设备
  • LibCurl HTTP部分详细介绍

    目录索引 xff1a 一 LibCurl基本编程框架 二 一些基本的函数 三 curl easy setopt函数部分选项介绍 四 curl easy perform 函数说明 xff08 error 状态码 xff09 五 libcurl
  • navicat连接oracle报错:ORA-12737 Instant Client Light:unsupported server character set ZHS16GBK

    今天使用Navicat连接Oracle数据库 xff0c 报了下面的这个错误 xff1a ORA 12737 Instant Client Light unsupported server character set ZHS16GBK 从这
  • VMWare报错"指定的文件不是虚拟磁盘"或“The file specified is not a virtual disk”

    今天打开原来创建的虚拟机 xff0c 突然报错 指定的文件不是虚拟磁盘 xff0c 如下图 xff1a 由于之前这个虚拟机创建了快照 xff0c 因此下面的解决方法是基于快照的 1 打开虚拟机的 vmx文件 xff0c 我的虚拟机名字为 U
  • Javascript模块加载框架——seajs

    最近看了一些开源web的项目 xff0c 发现其前台采用的框架seajs在编写JavaScript代码上很是方便 xff0c 现将学习的记录记于此 1 什么是JavaScript模块加载 为了解决不同javascript库里操作对象的命名冲
  • 2016年底总结

    一年又过去了 xff0c 在此简单说说这一年的收获和感受吧 一 说说考试 今年参加了两场考试 xff0c 一个是注册电气工程师 xff08 供配电 xff09 考试 xff0c 另外一个是一级建造师考试 两个考试均在9月份进行 xff0c
  • JS实现浏览器打印、打印预览

    目前正在做浏览器端采用JS方式实现打印这么一个功能 xff0c JS打印实现的方法很多 xff0c 但是兼容各个浏览器实现打印预览的功能有些棘手 xff0c 现将实现的内容及遇到的问题记录下来 xff0c 希望有大牛看到所提的问题后可以给予
  • STM32流水灯

    这个是根据51的基础上改的 一看就懂 直接在main c编辑就行 而不用去弄什么固件库 寄存器 这个是8个灯 然后设置A0 A7口为Output 推挽输出 就行 直接在user的main c中写就好 USER CODE BEGIN Head
  • PX4Ubuntu16.04环境搭建

    一 在虚拟机上安装一个新的ubuntu16 04系统 二 打开PX4的GITHUB主页 https github com PX4 Firmware 1 按照教程 这些脚本已经在干净的Ubuntu LTS 16 04和Ubuntu LTS 1
  • ucosII 信号量使用总结(举例讲解)

    概述 信号量用于 xff1a 1 控制共享资源的使用权 xff08 满足互斥条件 xff09 2 标志某时间的发生 3 使2个任务的行为同步 OSSemCreate 赋初值 OSSemCreate INT16U cnt xff0c cnt为
  • 用supervisor管理进程报错 “exit status 1 not expected”

    查看supervisor的日志发现报错 xff1a tail f var log supervisor supervisord log exited cyberwing domain numbercard exit status 1 not
  • Linux下core文件产生的一些注意问题

    前面转载了一篇文章关于core文件的产生和调试使用的设置 xff0c 但在使用有一些需要注意的问题 xff0c 如 在什么情况 才会正确地产生core文件 列出一些常见问题 xff1a 一 xff0c 如何使用core文件 1 使用core