【问题标题】:localtime() crashing with segmentation fault in clocaltime() 在 c 中因分段错误而崩溃
【发布时间】:2014-04-26 11:21:07
【问题描述】:

追查原因有点麻烦。

这里是代码位:

    #include <time.h>
time_t now;
struct tm *mytime;
char yyyy[5];
char mm[3];
char dd[3];
char mname[10];
if(time(&now)!=(time_t)(-1))
{
    mytime=localtime(&now);
    strftime(yyyy, sizeof(yyyy), "%Y", mytime);
    strftime(mm, sizeof(mm), "%m", mytime);
    strftime(dd, sizeof(dd), "%d", mytime);
    strftime(mname, sizeof(mname), "%B", mytime);
}

它在localtime 行崩溃:

Segmentation fault (core dumped)

有什么想法吗?

【问题讨论】:

  • 这里也一样。我的盒子上没有核心转储(Lubuntu 13.10 上的 gcc 4.8.1/glibc 2.17)。
  • localtime() 上崩溃的证据是什么?
  • 证据是我放入了一些printf 语句来隔离代码中导致错误的行。
  • 1) 与其讨论证据,不如张贴:使用的代码和相应的输出。添加printf() 时,可能会因printf() 而出现故障。 2)考虑struct tm mytime; mytime = *localtime(&amp;now); if (0==strftime(yyyy, sizeof(yyyy), "%Y", &amp;mytime)) Handle_Error();

标签: c fault localtime


【解决方案1】:

示例代码对我来说运行良好。发布您的完整代码?或者将您的示例减少到最小可能仍然会重现问题。并在你的核心“gdb -c a.core a.out”上运行 gdb 并获得回溯(bt)。

localtime 的一个问题是返回的指针是指向静态全局变量的指针,随后对 localtime 的调用会更新该变量。很久以前把我绊倒了一次。

struct tm *localtime(const time_t *time)

返回值是一个指向静态分解时间结构的指针,该结构可能被后续调用任何日期和时间函数覆盖。 (但没有其他库函数覆盖此对象的内容。)

来自: http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_17.html

关于搜索核心文件:

另见core dumped - but core file is not in current directory?

确保系统可以写入核心文件。
* 对我来说,在一个示例 ununtu system ulimit -c 显示 0 *

ulimit -c unlimited

检查使用的模式并将模式更改为一个简单的位置或不同的位置。

cat /proc/sys/kernel/core_pattern
#sysctl -w kernel.core_pattern=core

搜索一些常见位置并查看 /var/log/messages:

ls /var/crash /var/cache/abrt /var/spool/abrt/ /tmp/*core*
tail /var/log/messages

在 ubuntu 上检查 apport 服务配置和 init/rcfiles:

find /etc/ |grep appo

【讨论】:

  • 虽然说生成了核心文件,但核心文件并不存在。我需要哪些编译器标志才能生成包含有用数据的核心文件?
  • 编译器不控制核心文件的生成或位置。这是系统设置。你在linux上吗?你用的是什么风格的操作系统和版本?
  • 查看 /var/crash 或 /var/cache/abrt 或。 /var/spool/abrt/ 或其他取决于您的系统配置。另见stackoverflow.com/questions/2065912/…
  • 不,它不在这些目录中。 $ uname -a Linux marple.physast 3.2.0-60-generic #91-Ubuntu SMP Wed Feb 19 03:54:44 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
  • 嗯。 Ubuntu。 Grep 用于 /etc 和内核中的 corefiles 配置。也许从find /etc -name "*core*"find /etc -type f -exec grep core {} + 开始。查看找到的文件。有任何关于位置或名称的线索吗?还要检查您的ulimit -c,就像其他stackoverflow问题一样。
【解决方案2】:

这可能是也可能不是您的问题? 仍然没有足够的信息来确定你在做什么。 我会认为本地时间不是问题,但在 printfs 的某个地方存在问题。 . .

你是如何编译你的项目的? g++ 还是 gcc?

你能打印一个字符串吗? (相对于字符串 ptr) 你的上下文中的字符串是什么?

这里有1个问题:

fprintf(stdout,"# Single electron capture cross sections, %s state-selective\n",res);

如果 string 是 typedef a char[] 那么在 func args 中传递一个指向它的指针会更好吗?

编译你的样本做一些假设并添加调试(-g3):

gcc -g3 stackoverflow_localtime_crash.c -o socrash

./socrash 

# Single electron capture cross sections, RESSTRING state-selective
# Magic number=20032014, 20 March 2014, 
# Single electron capture cross sections, RESSTRING state-selective
# ^0+ +  -> ^-1+ + ^+
# Method=MCLZ
#  et al. 2014, to be submitted
# ----------------------------------------------------------------------------
# Energy        Cross sections (10^-16 cm^2)
# (eV/u)        LABELSTRING                     �H���u�j 

* 更多 JUNK 跟随 res 字符串本身不能在堆栈中传入和打印 *

Segmentation fault (core dumped)

gdb -c core socrash 

Core was generated by `./socrash'.
Program terminated with signal 11, Segmentation fault.
[New process 10298]
#0  0xb770e713 in strlen () from /lib/tls/i686/cmov/libc.so.6
(gdb) bt
#0  0xb770e713 in strlen () from /lib/tls/i686/cmov/libc.so.6
#1  0xb76da6d9 in vfprintf () from /lib/tls/i686/cmov/libc.so.6
#2  0xb76e0b9f in fprintf () from /lib/tls/i686/cmov/libc.so.6
#3  0x08048a42 in prtcsheader (cs=0xbf9e907c, labels=0xbf9e90bc, res=0xbf9e90a8 "RESSTRING") at stackoverflow_localtime_crash.c:66
#4  0x08048b36 in main (argc=Cannot access memory at address 0x0
) at stackoverflow_localtime_crash.c:80
(gdb) list
64      fprintf(stdout,"%-15s","# (eV/u)");
65      for(i=0;labels[i]!=NULL;i++)
66          fprintf(stdout,"\t%-14s",labels[i]);
67      fprintf(stdout,"\t%-14s","Total");
68  
69  return 0;
(gdb) 

*见第66行也有问题* 很可能是我声明字符串的方式:-P

66          fprintf(stdout,"\t%-14s",labels[i]);

* 如果你自己能找到一个核心文件,那将是一个很大的帮助!!! *

如果你找不到核心,那么也许你可以使用 ltrace。 运行 strace 以跟踪进程执行的所有系统调用。 运行 ltrace 以跟踪进程执行的所有 lib 调用。

试试:

strace ls

ltrace ls

关于我的崩溃示例:

ltrace ./socrash 1>stdout.log 2>socrash_ltrace.log
less socrash_ltrace.log 

【讨论】:

  • string is char * $ gcc --version gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 编译器选项:-Wall -std=gnu99
  • labels 是以 NULL 结尾的字符串数组,即char **。所以labelsstring *,或者char **。但是,正如我之前所说,它在localtime() 通话中崩溃了。我在代码中放了一堆 printf 语句,以隔离导致分段错误的行。是localtime()
  • 鉴于所有信息,对 localtime() 的调用看起来都还不错。段错误附近的 printfs 行为可能不会给您失败的地方。 printf 放入输出缓冲区的所有内容可能都看不到。或者发生了一些不好但微妙的事情,导致代码稍后出现段错误。在所有调试 printfs 的末尾有一个 \n 吗?你没有多个线程,是吗?我们没有确切的信息可以继续,这就是为什么我们怀疑它不是当地时间。你试过 ltrace 吗?您是否检查了 ulimit -c 显示的内容?找核心?在编译时添加调试选项使核心更有用。
猜你喜欢
  • 2017-09-28
  • 1970-01-01
  • 2012-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-20
  • 1970-01-01
相关资源
最近更新 更多