程序员自我修养-2-C实验

一、实验一

1. 实验代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <setjmp.h>

void func_bye_1(void)
{
    printf("%s called\n", __func__);
}
void func_bye_2(void)
{
    printf("%s called\n", __func__);
}

int test_atexit(void)
{
    int ret;
    ret = atexit(func_bye_1);
    if (ret != 0) {
        fprintf(stderr, "cannot set exit func\n");
        return ret;
    }
    ret = atexit(func_bye_2); //看起来注册多个是头插法
    if (ret != 0) {
        fprintf(stderr, "cannot set exit func\n");
        return ret;
    }
    return 0;
}

int get_sum(int num, ...)
{
    int sum = 0;
    int *p = &num + 1; //指向下一个参数
    printf("%s: &num=%p, p=%p\n", __func__, &num, p); //这是对的,p比&num多4B
    while (num--) {
        printf("%s: *p=%d\n", __func__, *p);
        sum += *p++;
    }
    return sum;
}

void test_indefi_params(void)
{
    int sum = get_sum(3, 10, 20, 30);
    printf("%s: sum=%d\n", __func__, sum);
}

void test_crash(void)
{
    char *p = NULL; //x86上exit_group不会被调用了
    *p = 1;
}

#if 0
jmp_buf mark_1;

void jump_fun(void)
{
    lonmgjmp(mark_1, 1);
}
void test_long_jmp(void)
{
    if (setjmp(mark_1) == 1) {
        printf("world!\n");
    } else {
        printf("hello \n");
        jump_fun();
    }
}
#endif

int main(int argc, char *argv[])
{
    int choice;

    if (argc == 1) {
        test_crash();
    }

    choice = atoi(argv[1]);

    if (choice == 1) {
        test_atexit();
    }
    if (choice == 2) {
        test_indefi_params(); //x86上测试失败
    }
    if (choice == 2) {
        //test_long_jmp();
    }

    printf("%s exit\n", __func__);
    
    return 0;
}


2. 实验结论

2.1 中途崩溃是不会调用exit()的(主动执行完会调用)

//(1)Ubuntu上测试:
my_test$ strace ./pp
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 4), ...}) = 0
brk(NULL)                               = 0x563e1c4d9000
brk(0x563e1c4fa000)                     = 0x563e1c4fa000
write(1, "main before crash\n", 18main before crash
)     = 18
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=NULL} ---
+++ killed by SIGSEGV (core dumped) +++

Segmentation fault (core dumped) //没有调用 exit_group()

//(2)嵌入式设备上测试:
prctl(PR_SET_DUMPABLE, SUID_DUMP_USER)  = 0
rt_sigaction(SIGTRAP, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTART}, {sa_handler=0x72f17fcca8, sa_mask=~[KILL STOP], sa_flags=SA_ONSTACK|SA_RESTART|SA_SIGINFO|0x800}, 8) = 0
getpid()                                = 19977
gettid()                                = 19977
rt_tgsigqueueinfo(19977, 19977, SIGTRAP, {si_signo=SIGTRAP, si_code=TRAP_BRKPT, si_pid=2244608512, si_uid=91}) = 0
rt_sigreturn({mask=[RTMIN]})            = 1
--- SIGTRAP {si_signo=SIGTRAP, si_code=TRAP_BRKPT, si_pid=2244608512, si_uid=91} ---
+++ killed by SIGTRAP +++
Trap

2.2 atexit() 测试成功, 注册函数的方式是头插法,进程退出时从链表头开始调用。

2.3 函数调用惯例测试失败。

2.4 longjmp测试失败。

 

posted on 2025-06-02 21:25  Hello-World3  阅读(17)  评论(0)    收藏  举报

导航