精华内容
下载资源
问答
  • (转载)如何避免 SIGSEGV如何避免SIGSEGV良好的编程习惯永远是最好的预防方法。良好的习惯包括:尽量按照C标准写程序。之所以说是尽量,是因为C标准有太多平台相关和无定义的行为,而其中一些实际上已经有既成事实的...

    ca56232b3bbedf9a539d07f37fffb99a.gif

    3144d8b7615c79d9f638db40d5689d26.gif

    a218af6549b45ee526caf607ebff1358.gif

    0f8df0e29816ae721419de940fb833d1.gif

    (转载)如何避免 SIGSEGV

    如何避免SIGSEGV

    良好的编程习惯永远是最好的预防方法。良好的习惯包括:

    尽量按照C标准写程序。之所以说是尽量,是因为C标准有太多平台相关和无定义的行为,而其中一些实际上已经有既成事实的标准了。例如C标准中,一个越界的指针导致的是无定义的行为,而在实际情况中,一个越界而未解引用的指针是不会带来灾难后果的。借用CU的一个例子,如下:

    1 #include

    2 #include

    3

    4 int main () {

    5     char a[] = "hello";

    6     char* p;

    7

    8     for ( p = a+5; p>=a; p-- )

    9         printf ("%c\n", *p);

    10

    11 }

    虽然循环结束后,p指向了数组a前一个元素,在C标准中这是一个无定义的行为,但实际上程序却是安全的,没有必要为了不让p成为一个野指针而把程序改写为:

    1 #include

    2 #include

    3

    4 int main () {

    5     char a[] = "hello";

    6     char* p;

    7

    8     for ( p = a+5; p!=a; p-- ) {

    9         printf ("%c\n", *p);

    10     }

    11     printf ("%c\n", *p);

    12 }

    当然,或许世界上真有编译器会对“越界但未解引用”的野指针进行处理,例如引发一个SIGSEGV。笔者无法100%保证,所以大家在实践中还是各自斟酌吧。

    彻底的懂得你的程序。和其它程序员不同的是,C程序员需要对自己的程序完全了解,做到精确控制。尤其在内存的分配和释放方面。在操作每一个指针前,你都应该清楚它所指向内存的出处(栈、堆、全局区),并清楚此内存的生存周期。只有明白的使用内存,才能最大限度的避免SIGSEGV的产生。

    大量使用assert。笔者偏好在程序中使用大量的assert,凡是有认为不该出现的情况,笔者就会加入一个assert做检查。虽然assert无法直接避免SIGSEGV,但它却能尽早的抛出错误。离错误越近,就越容易root cause。很多时候出现SIGSEGV时,程序已经跑飞很远了。

    打开-Wall  –Werror编译选项。如果程序是自己写的,0 warning应该始终是一项指标(0 warning不包括因为编译器版本不同而引起的warning)。一种常见的SIGSEGV来源于向函数传入了错误的参数类型。例如:

    1 #include

    2 #include

    3 #include

    4

    5 int main () {

    6     char buf[12];

    7     int buff;

    8

    9     strcpy (buff, "hello");

    10

    11 }

    这个例子中,本意是要向buf拷贝一个字符串,但由于有一个和buf名称很相近的buff变量,由于一个笔误(这个笔误很可能就来自你编辑器的自动补全,例如vim的ctrl – p, ctrl – n),strcpy如愿的引发了SIGSEGV。实际在编译期间,编译器就提示我们warning: passing argument 1 of `strcpy' makes pointer from integer without a cast,但我们忽略了。

    这就进一步要求我们尽量使用编译器的类型检查功能,包括多用函数少用宏(特别是完成复杂功能的宏),函数参数多用带类型的指针,少用void*指针等。此例就是我们在2.2节提到的不经意的行为。

    少用奇技淫巧,多用标准方法。好的程序应该逻辑清楚,干净整洁,像一篇朗朗上口的文章,让人一读就懂。那种充满晦涩语法、怪异招数的试验作品,是不受欢迎的。很多人喜欢把性能问题做为使用不标准方法的借口,实际上他们根本不知道对性能的影响如何,拿不出具体指标,全是想当然尔。笔者曾经在项目中,将一个执行频繁的异常处理函数用汇编重写,使该函数的执行周期从2000多个机器周期下降到40多个。满心欢喜的提交了一个patch给该项目的maintainer,得到的答复是:“张,你具体测试过你的patch能带来多大的性能提升吗?如果没有明显的数据,我是不愿意将优雅的C代码替换成这晦涩的汇编的。”于是我做了一个内核编译来测试patch,耗时15分钟,我的patch带来的整体性能提升大约为0.1%。所以,尽量写清楚明白的代码,不仅有利于避免SIGSEGV,也利于在出现SIGSEGV后进行调试。

    当你的一个需求,标准的方法不能满足时,只有两种可能:1.从一开始的设计就错了,才会导致错误的需求;2.你读过的代码太少,不知道业界解决该问题的标准方法是什么。计算机已经发展了几十年,如果你不是在做前沿研究,遇到一定得用非标准方法解决的问题的机会实在太小了。正如我们经常用gdb跟踪发现SIGSEGV发生在C库里,不要嚷嚷说C库有bug,大部情况是一开始你传入的参数就错了。

    小结

    无论如何我们应该感谢SIGSEGV,是它让我们能在不重启机器的情况下调试程序。相比那些由于内存使用错误而不得不一次又一次重启机器来debug的内核工程师,SIGSEGV让我们的生活变得轻松。理解SIGSEGV同时,我们也更加理解程序。希望这篇文档对初学C语言的同志有些许帮助。

    展开全文
  • 我在c中编写了一个使用Qt 4.7.4的应用程序....关闭应用程序时,有时它会与SIGSEGV崩溃并发生以下回溯:#0 malloc_consolidate (av=0x7ffff58b21c0) at malloc.c:5155#1 0x00007ffff5591659 in malloc_consolidate ...

    我在c中编写了一个使用Qt 4.7.4的应用程序.启动时,它会加载一些自动编写的动态库,这些库也使用Qt(如果这在某种程度上有用).

    关闭应用程序时,有时它会与SIGSEGV崩溃并发生以下回溯:

    #0 malloc_consolidate (av=0x7ffff58b21c0) at malloc.c:5155

    #1 0x00007ffff5591659 in malloc_consolidate (av=0x7ffff58b21c0) at malloc.c:5115

    #2 _int_free (av=0x7ffff58b21c0, p=) at malloc.c:5034

    #3 0x00007ffff5594d7c in __GI___libc_free (mem=) at malloc.c:3738

    #4 0x00007ffff5e9e0ac in QString::free (d=0xdb0290) at tools/qstring.cpp:1186

    #5 0x00007fffe60b3d83 in ~QString (this=0xba0328, __in_chrg=) at ../../include/QtCore/../../src/corelib/tools/qstring.h:883

    #6 node_destruct (to=0xba0328, from=0xba0328, this=) at ../../include/QtCore/../../src/corelib/tools/qlist.h:420

    #7 QList::free (data=0xba0310, this=) at ../../include/QtCore/../../src/corelib/tools/qlist.h:744

    #8 0x00007fffe60c2b49 in ~QList (this=0xba0388, __in_chrg=) at ../../include/QtCore/../../src/corelib/tools/qlist.h:719

    #9 ~QStringList (this=0xba0388, __in_chrg=) at ../../include/QtCore/../../src/corelib/tools/qstringlist.h:66

    #10 ~SignalHook (this=0xba0358, __in_chrg=) at qdbusconnection_p.h:121

    #11 ~QHashNode (this=0xba0340, __in_chrg=) at ../../include/QtCore/../../src/corelib/tools/qhash.h:216

    #12 QHash::deleteNode2 (node=0xba0340) at ../../include/QtCore/../../src/corelib/tools/qhash.h:519

    #13 0x00007ffff5e754da in QHashData::free_helper (this=0xd8aec0, node_delete=0x7fffe60c2ae0 ::deleteNode2(QHashData::Node*)>) at tools/qhash.cpp:271

    #14 0x00007fffe60ba733 in freeData (x=, this=) at ../../include/QtCore/../../src/corelib/tools/qhash.h:568

    #15 ~QHash (this=, __in_chrg=) at ../../include/QtCore/../../src/corelib/tools/qhash.h:284

    #16 ~QMultiHash (this=0xba3498, __in_chrg=) at ../../include/QtCore/../../src/corelib/tools/qhash.h:922

    #17 ~QMultiHash (this=0xba3498, __in_chrg=) at qdbusintegrator.cpp:998

    #18 QDBusConnectionPrivate::~QDBusConnectionPrivate (this=0xba33f0, __in_chrg=) at qdbusintegrator.cpp:998

    #19 0x00007fffe60ba939 in QDBusConnectionPrivate::~QDBusConnectionPrivate (this=0xba33f0, __in_chrg=) at qdbusintegrator.cpp:1016

    #20 0x00007fffe60afe43 in ~QDBusDefaultConnection (this=0xba55a0, __in_chrg=) at qdbusconnection.cpp:993

    #21 QGlobalStaticDeleter::~QGlobalStaticDeleter (this=0x7fffe63102f8, __in_chrg=) at ../../include/QtCore/../../src/corelib/global/qglobal.h:1825

    #22 0x00007ffff5553821 in __run_exit_handlers (status=0, listp=0x7ffff58b05a8, run_list_atexit=true) at exit.c:78

    #23 0x00007ffff55538a5 in __GI_exit (status=) at exit.c:100

    #24 0x00007ffff5539314 in __libc_start_main (main=0x493935 , argc=1, ubp_av=0x7fffffffde58, init=, fini=, rtld_fini=, stack_end=0x7fffffffde48) at libc-start.c:258

    #25 0x0000000000421a99 in _start ()

    有时这一个

    #0 malloc_consolidate (av=0x7ffff58b21c0) at malloc.c:5155

    #1 0x00007ffff5591659 in malloc_consolidate (av=0x7ffff58b21c0) at malloc.c:5115

    #2 _int_free (av=0x7ffff58b21c0, p=) at malloc.c:5034

    #3 0x00007ffff5594d7c in __GI___libc_free (mem=) at malloc.c:3738

    #4 0x00007ffff5f4d5a9 in ~QVector (this=0x767c40, __in_chrg=) at ../../include/QtCore/../../src/corelib/tools/qvector.h:119

    #5 QGlobalStaticDeleter >::~QGlobalStaticDeleter (this=0x7ffff6274898, __in_chrg=) at ../../include/QtCore/../../src/corelib/global/qglobal.h:1825

    #6 0x00007ffff5553c3d in __cxa_finalize (d=0x7ffff6273d20) at cxa_finalize.c:56

    #7 0x00007ffff5e3e0a6 in __do_global_dtors_aux () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4

    #8 0x00007fffffffd7c0 in ?? ()

    #9 0x00007fffffffdd30 in ?? ()

    #10 0x00007ffff5f9e5a1 in _fini () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4

    #11 0x000000000000009f in ?? ()

    #12 0x00007ffff7deb105 in ?? () from /lib64/ld-linux-x86-64.so.2

    或者这个

    #0 malloc_consolidate (av=0x7ffff58b21c0) at malloc.c:5155

    #1 0x00007ffff5591659 in malloc_consolidate (av=0x7ffff58b21c0) at malloc.c:5115

    #2 _int_free (av=0x7ffff58b21c0, p=) at malloc.c:5034

    #3 0x00007ffff5594d7c in __GI___libc_free (mem=) at malloc.c:3738

    #4 0x00007ffff5e86bbe in freeData (x=, this=) at ../../include/QtCore/../../src/corelib/tools/qmap.h:654

    #5 ~QMap (this=0x10af198, __in_chrg=) at ../../include/QtCore/../../src/corelib/tools/qmap.h:187

    #6 ~QMap (this=0x10af198, __in_chrg=) at tools/qvector.h:430

    #7 ~QRegExpAutomatonState (this=0x10af180, __in_chrg=) at tools/qregexp.cpp:947

    #8 QVector::free (x=0x10af0f0, this=) at tools/qvector.h:438

    #9 0x00007ffff5e969a9 in clear (this=) at tools/qcache.h:139

    #10 ~QCache (this=, __in_chrg=) at tools/qcache.h:103

    #11 QGlobalStaticDeleter >::~QGlobalStaticDeleter (this=0x7ffff6274368, __in_chrg=) at ../../include/QtCore/../../src/corelib/global/qglobal.h:1825

    #12 0x00007ffff5553821 in __run_exit_handlers (status=0, listp=0x7ffff58b05a8, run_list_atexit=true) at exit.c:78

    #13 0x00007ffff55538a5 in __GI_exit (status=) at exit.c:100

    #14 0x00007ffff5539314 in __libc_start_main (main=0x493935 , argc=1, ubp_av=0x7fffffffde58, init=, fini=, rtld_fini=, stack_end=0x7fffffffde48) at libc-start.c:258

    #15 0x0000000000421a99 in _start ()

    还有一些……

    我认为它们都是相关的,但我真的无法弄清楚这是如何以及为什么会发生这种情况(请注意,我的代码中没有列出任何代码).

    非常感谢您提供一些提示,为什么会发生这种情况或者我应该从哪里开始搜索.

    展开全文
  • <code class="language-bash">#include<stdio.h> #include<cstring> #define MaxV 100 //宏定义最大顶点数 ...调试过程中会出现program received signal sigsegv问题,求解!</p>
  • #include<stdio.h> #include<stdlib.h> typedef struct link { int data; struct link *next; }Link; Link *AppendNode(Link *head); //添加节点 void DisplyNode(Link *head);...}
  • 编写了一个简单的helloword代码,编译之后出现 ![图片说明](https://img-ask.csdn.net/upload/202004/11/1586593505_280765.png) 然后我按了一下f8,出现 ![图片说明]...
  • 题目: [img=https://img-bbs.csdn.net/upload/201508/31/1441008554_800669.png][/img] 我的代码: #include <stdio.h> #include <stdlib.h> typedef struct LNode{ ...先行拜谢~
  • c语言信号处理sigaction(2011-04-18 23:45:19)标签:c语言信号处理sigactionsighupit分类:c信号安装函数sigaction(int signum,const struct sigaction *act,struct sigaction*oldact)的第二个参数是一个指向...

    c语言信号处理sigaction

    a4c26d1e5885305701be709a3d33442f.png

    (2011-04-18 23:45:19)

    标签:

    c语言

    信号处理

    sigaction

    sighup

    it

    分类:

    c

    信号安装函数sigaction(int signum,const struct sigaction *act,struct sigaction

    *oldact)的第二个参数是一个指向sigaction结构的指针(结构体名称与函数名一样,千万别弄混淆了)。在结构sigaction的实例中,指定了对特定信号的处理,信号所传递的信息,信号处理函数执行过程中应屏蔽掉哪些函数等。当然,此指针也可以为NULL,进程会以默认方式处理信号。以下就简单介绍一下sigaction结构以及一般的用法。

    对于内核头文件而言,struct sigaction

    结构体定义在kernel/include/asm/signal.h,此头文件又被kernel/include/linux/signal.h包含。

    对于用户空间的头文件而言,struct sigaction定义在

    /usr/include/bits/sigaction.h,此头文件又被/usr/include/signal.h包含,所以应用程序中如果用到此结构,只要#include

    即可。注意内核中的定义和应用程序中的定义是不一样的,内核空间的sigaction结构只支持函数类型为

    __sighandler_t的信号处理函数,不能处理信号传递的额外信息。具体定义如下:

    ……

    typedef void (*__sighandler_t)(int);

    ……

    #ifdef __KERNEL__

    struct old_sigaction {

    __sighandler_t sa_handler;

    old_sigset_t sa_mask;

    unsigned long sa_flags;

    void (*sa_restorer)(void);

    };

    struct sigaction {

    __sighandler_t sa_handler;

    unsigned long sa_flags;

    void (*sa_restorer)(void);

    sigset_t sa_mask;

    };

    struct k_sigaction {

    struct sigaction sa;

    };

    #else

    struct sigaction {

    union {

    __sighandler_t _sa_handler;

    void (*_sa_sigaction)(int, struct siginfo *, void *);

    } _u;

    sigset_t sa_mask;

    unsigned long sa_flags;

    void (*sa_restorer)(void);

    };

    #define sa_handler _u._sa_handler

    #define sa_sigaction _u._sa_sigaction

    #endif

    sa_handler的原型是一个参数为int,返回类型为void的函数指针。参数即为信号值,所以信号不能传递除信号值之外的任何信息;

    sa_sigaction 的原型是一个带三个参数,类型分别为int,struct siginfo *,void

    *,返回类型为void的函数指针。第一个参数为信号值;第二个参数是一个指向struct

    siginfo结构的指针,此结构中包含信号携带的数据值;第三个参数没有使用。

    sa_mask指定在信号处理程序执行过程中,哪些信号应当被阻塞。默认当前信号本身被阻塞。

    sa_flags

    包含了许多标志位,比较重要的一个是SA_SIGINFO,当设定了该标志位时,表示信号附带的参数可以传递到信号处理函数中。即使

    sa_sigaction指定信号处理函数,如果不设置SA_SIGINFO,信号处理函数同样不能得到信号传递过来的数据,在信号处理函数中对这些信息的访问都将导致段错误。

    sa_restorer已过时,POSIX不支持它,不应再使用。

    因此,当你的信号需要接收附加信息的时候,你必须给sa_sigaction赋信号处理函数指针,同时还要给sa_flags赋SA_SIGINFO,类似下面的代码:

    #include

    ……

    void sig_handler_with_arg(int sig,siginfo_t *sig_info,void

    *unused){……}

    int main(int argc,char **argv)

    {

    struct sigaction sig_act;

    ……

    sigemptyset(&sig_act.sa_mask);

    sig_act.sa_sigaction=sig_handler_with_arg;

    sig_act.sa_flags=SA_SIGINFO;

    ……

    }

    如果你的应用程序只需要接收信号,而不需要接收额外信息,那你需要的设置的是sa_handler,而不是sa_sigaction,你的程序可能类似下面的代码:

    #include

    ……

    void sig_handler(int sig){……}

    int main(int argc,char **argv)

    {

    struct sigaction sig_act;

    ……

    sigemptyset(&sig_act.sa_mask);

    sig_act.sa_handler=sig_handler;

    sig_act.sa_flags=0;

    ……

    }

    如果需要更详细说明,请参阅sigaction的man手册。

    补充:

    简而言之就是:

    //自定义退出函数

    sigact.sa_handler = mysighandler;

    sigemptyset(&sigact.sa_mask);

    sigact.sa_flags = 0;

    sigaction(SIGINT, &sigact, NULL);

    sigaction(SIGTERM, &sigact, NULL);

    sigaction(SIGQUIT, &sigact, NULL);

    或者利用signal函数进行信号捕捉:

    void (*signal(int signo, void (*handler)(int)))(int);

    当signal到来时,程序运行某函数,函数由你自己指定。

    附带各种信号定义:

    在终端使用kill -l 命令可以显示所有的信号。

    $kill -l

    1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL

    5) SIGTRAP 6) SIGABRT 7) SIGBUS

    a4c26d1e5885305701be709a3d33442f.png

    SIGFPE

    9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2

    13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT

    17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP

    21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU

    25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH

    29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN

    35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4

    39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8

    43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46)

    SIGRTMIN+12

    47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50)

    SIGRTMAX-14

    51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54)

    SIGRTMAX-10

    55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6

    59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2

    63) SIGRTMAX-1 64) SIGRTMAX

    其中前面31个信号为不可靠信号(非实时的,可能会出现信号的丢失),后面的信号为可靠信号(实时的real_time,对信号

    排队,不会丢失)。

    1) SIGHUP (挂起) 当运行进程的用户注销时通知该进程,使进程终止

    2) SIGINT (中断) 当用户按下时,通知前台进程组终止进程

    3) SIGQUIT (退出) 用户按下或时通知进程,使进程终止

    4) SIGILL (非法指令) 执行了非法指令,如可执行文件本身出现错误、试图执行数据段、堆栈溢出

    5) SIGTRAP 由断点指令或其它trap指令产生. 由debugger使用

    6) SIGABRT (异常中止) 调用abort函数生成的信号

    7) SIGBUS 非法地址, 包括内存地址对齐(alignment)出错. eg: 访问一个四个字长的整数,

    但其地址不是4的倍数.

    8) SIGFPE (算术异常) 发生致命算术运算错误,包括浮点运算错误、溢出及除数为0.

    9) SIGKILL (确认杀死) 当用户通过kill -9命令向进程发送信号时,可靠的终止进程

    10) SIGUSR1 用户使用

    11) SIGSEGV (段越界) 当进程尝试访问不属于自己的内存空间导致内存错误时,终止进程

    12) SIGUSR2 用户使用

    13) SIGPIPE 写至无读进程的管道, 或者Socket通信SOCT_STREAM的读进程已经终止,而再写入。

    14) SIGALRM (超时) alarm函数使用该信号,时钟定时器超时响应

    15) SIGTERM (软中断) 使用不带参数的kill命令时终止进程

    17) SIGCHLD (子进程结束) 当子进程终止时通知父进程

    18) SIGCONT (暂停进程继续) 让一个停止(stopped)的进程继续执行. 本信号不能被阻塞.

    19) SIGSTOP (停止) 作业控制信号,暂停停止(stopped)进程的执行. 本信号不能被阻塞, 处理或忽略.

    20) SIGTSTP (暂停/停止) 交互式停止信号, Ctrl-Z 发出这个信号

    21) SIGTTIN 当后台作业要从用户终端读数据时, 终端驱动程序产生SIGTTIN信号

    22) SIGTTOU 当后台作业要往用户终端写数据时, 终端驱动程序产生SIGTTOU信号

    23) SIGURG 有"紧急"数据或网络上带外数据到达socket时产生.

    24) SIGXCPU 超过CPU时间资源限制. 这个限制可以由getrlimit/setrlimit来读取/改变。

    25) SIGXFSZ 当进程企图扩大文件以至于超过文件大小资源限制。

    26) SIGVTALRM 虚拟时钟信号. 类似于SIGALRM, 但是计算的是该进程占用的CPU时间.

    27) SIGPROF (梗概时间超时) setitimer(2)函数设置的梗概统计间隔计时器(profiling interval

    timer)

    28) SIGWINCH 窗口大小改变时发出.

    29) SIGIO(异步I/O) 文件描述符准备就绪, 可以开始进行输入/输出操作.

    30) SIGPWR 电源失效/重启动

    31) SIGSYS 非法的系统调用。

    在以上列出的信号中,

    程序不可捕获、阻塞或忽略的信号有:SIGKILL,SIGSTOP

    不能恢复至默认动作的信号有:SIGILL,SIGTRAP

    默认会导致进程流产的信号有:SIGABRT,SIGBUS,SIGFPE,SIGILL,SIGIOT,SIGQUIT,SIGSEGV,SIGTRAP,SIGXCPU,SIGXFSZ

    默认会导致进程退出的信号有:SIGALRM,SIGHUP,SIGINT,SIGKILL,SIGPIPE,SIGPOLL,SIGPROF,SIGSYS,SIGTERM,SIGUSR1,SIGUSR2,SIGVTALRM

    默认会导致进程停止的信号有:SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU

    默认进程忽略的信号有:SIGCHLD,SIGPWR,SIGURG,SIGWINCH

    此外,SIGIO在SVR4是退出,在4.3BSD中是忽略;SIGCONT在进程挂起时是继续,否则是忽略,不能被阻塞。

    在Unix/Linux中signal函数是比较复杂的一个,其定义原型如下:

    void (*signal(int signo,void (*func)(int))) (int)

    这个函数中,最外层的函数体

    void (* XXX

    )(int)表明是一个指针,指向一个函数XXX的指针,XXX所代表的函数需要一个int型的参数,返回void

    signal(int signo, void(*func)(int))是signal函数的主体.

    需要两个参数int型的signo以及一个指向函数的函数.

    void (*func)(int).

    正是由于其复杂性,在[Plauger 1992]用typedef来对其进行简化

    typedef void Sigfuc(int);//这里可以看成一个返回值 .

    再对signal函数进行简化就是这样的了

    Sigfunc *signal(int,Sigfuc *);

    在signal.h头文件中还有以下几个定义

    #define SIG_ERR (void (*)())-1

    #define SIG_DFL (void (*)())0

    #define SIG_IGN (void (*)())1

    处理不当导致的问题请参照下面网址

    http://www.diybl.com/course/3_program/c++/cppjs/20090831/173152.html

    分享:

    a4c26d1e5885305701be709a3d33442f.png喜欢

    0

    a4c26d1e5885305701be709a3d33442f.png赠金笔

    加载中,请稍候......

    评论加载中,请稍候...

    发评论

    登录名: 密码: 找回密码 注册记住登录状态

    昵   称:

    评论并转载此博文

    a4c26d1e5885305701be709a3d33442f.png

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

    展开全文
  • c语言中对字符串常量有特殊的处理,在内存中开辟出一段类似祖父数组的东西来存放字符串常量 所以,"I am Felaim"是存在于内存中的,并且有一个内存地址 #include <iostream> int main() { // 把常量字符串...

    第九章 指针

    第七节 字符串的指针和指向字符串的指针变量

    1. 字符串表示形式

    • c语言中对字符串常量有特殊的处理,在内存中开辟出一段类似祖父数组的东西来存放字符串常量
      所以,"I am Felaim"是存在于内存中的,并且有一个内存地址
    #include <iostream>
    
    int main() {
    
        // 把常量字符串拷贝到数组中去, 内存地址不相同
        char mystr[] = "I am Felaim!";
        char mystr1[] = "I am Felaim!";
    
        printf("%s\n", mystr);
        printf("%s\n", mystr1);
    
        //不是拷贝,相当于把内存中常量的首地址赋给了指针,
        // 所以指向了相同地址
        char *pmystr = "I am Felaim";//这是字符串常量
        char *pmystr1 = "I am Felaim";
    
        //    Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
    //    pmystr[4] = '1';//常量字符串只能用来读,不能用来写,
    
        return 0;
    }
    
    • 实例
    #include <iostream>
    
    int main() {
    
        // 把常量字符串拷贝到数组中去, 内存地址不相同
        char mystr[] = "I am Felaim!";
        char b[100];//保证比a字符数组长
        char *p1, *p2;
        p1 = mystr;
        p2 = b;
        int i;
    
        for(;*p1 != '\0'; p1++, p2++){
            *p2 = *p1;
        }
        *p2 = '\0';
    
    //    for (i = 0; *(mystr + i) != '\0'; i++) {
    //        *(b + i) = *(mystr + i);//b[i] = mystr[i]
    //    }
    //    *(b + i) = '\0';
        printf("mystr: %s\n", mystr);
        printf("b: %s\n", b);
    
    
        return 0;
    }
    

    2. 字符串指针做函数参数

    #include <iostream>
    
    // 字符数组名做参数,将实参首地址传递给from,所以from和a指向同一个单元,
    // to就和b实参指向同一个单元
    void copystr(char from[], char to[]) {
        int i = 0;
        while (from[i] != '\0') {
            to[i] = from[i];//逐个字符拷贝,一直到遇到'\0'退出
            i++;
        }
    
        to[i] = '\0';
    }
    
    //传递指针
    void copystrp(char *from, char *to) {
    //    int i = 0;
    //    while (from[i] != '\0') {
    //        to[i] = from[i];//逐个字符拷贝,一直到遇到'\0'退出
    //        i++;
    //    }
    //    to[i] = '\0';
    
        while (*from) {
            *to++ = *from++;
        }
        *to = '\0';
    }
    
    int main() {
    
        char a[] = "this is source";
        char b[] = "I am Felaim!!!!!!!!!!!!!!"; //必须保证b比a大,不然拷贝的时候内存溢出
    
        printf("a: %s\n", a);
        printf("b: %s\n", b);
    
    //    copystr(a, b);
        copystrp(a, b);
        printf("a: %s\n", a);
        printf("b: %s\n", b);
    
        return 0;
    }
    

    3. 字符指针变量与字符数组

    • 字符数组是由若干个元素组成的,每个元素中存放一个字符;字符指针变量中存放的是字符串首地址,
      仅仅是地址
    #include <iostream>
    #include <cstring>
    
    int main() {
        // 方式一
    //   char str[100] = "I am Felaim!";//定义时初始化,相当于拷贝字符串内容到str中
    
        //不能分成两行写成如下方式
    //   char str[100];
    //   str = "I am Felaim!";
    
        //可以通过strcpy来进行copy
    //    char str[100];
    //    strcpy(str, "I am Felaim!");
    
        //字符串常量在内存中有固定地址,这里的赋值只是让字符指针a指向这个地址而已
        char *a;
        a = "I am Felaim!";
    
        // 指针变量的值可以改变
        a = a + 5;//指向F
        printf("%s\n", a);
    
        // 数组首地址是不可以改变的,下面的方式错误
    //    char a[] = "I am Felaim!";
    //    a = a+5;
    
        return 0;
    }
    
    展开全文
  • signal SIGSEGV

    千次阅读 2020-02-06 09:19:40
    一种报错
  • C语言笔记

    2021-03-29 00:01:31
    C语言笔记 C语言特性 gcc编译 全局变量与局部变量在内存中的位置 数组 枚举 指针 C 标准库 <assert.h> <ctype.h> <math.h> <signal.h> <stdlib.h> 内存管理 C语言笔记 C语言特性 C ...
  • C++ SIGSEGV check list

    千次阅读 2017-04-18 20:20:03
    C++丢了很长时间了,没想到还有捡回来的一天,各种不适应,尤其是指针相关的,SIGSEGV这几天真没少见,总结下自己遇到的SIGSEGV case,下面这个可以作为一个check-list: null指针解引用,这个就不说了,解引用前...
  • HLS:@E Simulation failed: SIGSEGV. 前言 在HLS工具中使用C仿真时报如下错误,经定位问题后发现有数组开辟方式的问题。 错误描述 @E Simulation failed: ...HLS的C仿真中不能用C语言中的这种方式来定义数组,需
  • C语言】输入任何内容出现program received signal SIGSEGV, Segmentation fault. C语言 scanf语句中漏了&
  • C语言中,程序默认的执行顺序是按语句出现的先后顺序按序执行。如果你想要让程序做一些决定,根据不同的情况做不同的事情,例如根据时间打印“早上好”或者“晚上好”,这可以通过控制流语句实现。分支结构a ? b : c...
  • 大二C语言总结

    2021-03-14 22:27:19
    Linux C语言2020大二上半学期总结,整理到吐血 内存管理 整数页为4096 = 4K 进程和程序 程序 - 硬盘上的可执行文件 进程 - 在内存中运行的程序 进程中的内存区域划分 –代码区-来存放可执行文件的操作指令...
  • C++ SIGSEGV报错

    2020-09-03 00:05:09
    今天写代码碰到了一个特别离谱的问题,程序运行着突然就崩溃了。 最后原因是因为在之前调用的函数中出现了数组越界的情况,但是当时并没有报错,程序仍然正常运行。 直到我调用另一个函数时,程序才莫名其妙崩溃。...
  • 如何避免SIGSEGV

    2014-10-03 23:52:27
    如何避免SIGSEGV 良好的编程习惯永远是最好的预防方法。良好的习惯包括: 尽量按照C标准写程序。之所以说是尽量,是因为C标准有太多平台相关和无定义的行为,而其中一些实际上已经有既成事实的标准了。例如C标准中...
  • 理解SIGBUS与SIGSEGV

    2014-12-22 17:51:54
    看到第三方平台上给出的bug信息,所以查了一下SIGBUS与SIGSEGV: 理解SIGBUS与SIGSEGV Q: SIGSEGV我能理解,但有时碰上SIGBUS,这该如何理解。 A: nkwht@smth nkwht用Google获取这样一些知识。有多种可能...
  • 这里是一只大一的菜狗,要完成老师布置的一个程序,目的是做一个学生信息系统:...Program received signal SIGSEGV, Segmentation fault,系统提示的断点是在38行getnext那个函数</p>
  • C语言信号处理

    千次阅读 2017-08-13 16:39:46
    C语言信号处理
  • 关于QT显示SIGSEGV报错的解决方法

    千次阅读 2020-06-24 12:13:01
    最近在Linux下用QT进行界面编程时,遇到了诡异的SIGSEGV问题。经过2天各种搜索查询摸爬滚打,终于不小心碰到了解决方法。 正文: 这几天在Deepin系统上编写程序,采用了QT,写的是UI界面程序(Qt Widgets ...
  • C语言标准函数库

    千次阅读 2014-06-13 01:19:30
    http://blog.csdn.net/pipisorry/article/details/30398049C语言标准头 断言 字符类测试 (部分)库函数抛出的错误代码 浮点数运算 检测整型数据类型值范围 本土化 数学函数 “非局部跳转” 信号 可变参数列表 一些...
  • 关于C语言进程操作

    2021-08-15 12:59:49
    关于C语言进程操作 Linux标准库 <unistd.h> 符号常量 NULL // Null pointer SEEK_CUR // Set file offset to current plus offset. SEEK_END // Set file offset to EOF plus offset. SEEK_SET // Set file ...
  • C语言标准库函数

    2014-10-20 11:07:06
    C语言标准头 断言 字符类测试 (部分)库函数抛出的错误代码 浮点数运算 检测整型数据类型值范围 本土化 数学函数 “非局部跳转” 信号 可变参数列表 一些常数,类型和变量 输入和输出 ...
  • C语言 signal

    2019-04-24 21:29:28
    非法访问内存 → 11) SIGSEGV (段错误) 总线错误 → 7) SIGBUS kill命令产生信号:kill -SIGKILL pid(SIGKILL 代号 就是 9) kill函数:给指定进程发送指定信号 int kill(pid_t pid, int sig); 成功:0;失败...
  • 如代码 GET函数总是报SIGSEGV错误 小白求大神指点 ``` #include #include typedef char datatype; #define maxsize 64 typedef struct { datatype data[maxsize]; int top; }seqstack; typedef ...
  • C语言信号学习笔记

    千次阅读 2013-09-09 13:34:56
    C语言信号处理的简单笔记。主要取材于《C语言程序设计——现代方法》
  • c语言捕获kill信号Programs may want to catch the kill signals sent by the kill command in C programs on Linux so that it can gracefully shutdown itself before it is killed. For example, I have a daemon...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,314
精华内容 925
关键字:

c语言sigsegv

c语言 订阅