一个测试引发的思考

82 篇文章 0 订阅
49 篇文章 0 订阅

有赖机缘,写代码展示null指针调用类的成员函数、静态成员函数: (想在一份代码中完成)

考虑到会有SIGSGEV(无效内存引用),所以要有异常\错误处理方法。



1. 首先想到C++的try & catch:

#include <stdlib.h>
#include <utility>
#include <iostream>
using namespace std;

class A
{
public:
    A() : m_i(0)
    {

    }

public:
    void test_not_access()
    {
        cout << "ok!" << endl;
    }

    void test_read()
    {
        int dummy = m_i;
        cout << "ok!" << endl;
    }

    void test_write()
    {
        ++m_i;
        cout << "ok!" << endl;
    }

    static void test_read_write_static()
    {
        int dummy = ++s_i;
        cout << "ok!" << endl;
    }

private:
    int m_i;
    static int s_i;
};

int A::s_i = 0;

int main(int argc, char * argv[], char * envp[])
{
    A * pa = NULL;

    typedef void (A::*PFunc)(void);
    typedef pair<PFunc, const char *> Pair;
    Pair msg[3] =
    {
        make_pair
        (
            &A::test_not_access,
            "null pointer call function which donot access member:\n\t"
        ),
        make_pair
        (
            &A::test_read,
            "null pointer call function which read member:\n\t"
        ),
        make_pair
        (
            &A::test_write,
            "null pointer call function which write member:\n\t"
        )
    };

    for (int i = 0, size = sizeof(msg)/sizeof(msg[0]); i < size; ++i)
    {
        try
        {
            cout << msg[i].second;
            (pa->*msg[i].first)();
        }
        catch (...)
        {
            cout << "error!" << endl;
        }
    }

    try
    {
        cout << "null pointer call static function which read and write member:\n\t";
        pa->test_read_write_static();
        exit(0);
    }
    catch (...)
    {
        cout << "error!" << endl;
    }

    return(0);
}

发现:try & catch (...) 不能处理SIGSGEV (不知道C++的set_handle?... 之后,能不能处理过来)



2. 然后想到信号处理机制 signal、sigaction:

#include <stdlib.h>
#include <signal.h>
#include <utility>
#include <iostream>
using namespace std;

void sig_segv(int signo)
{
    cout << "error!" << endl;
}

class A
{
public:
    A() : m_i(0)
    {

    }

public:
    void test_not_access()
    {
        cout << "ok!" << endl;
    }

    void test_read()
    {
        int dummy = m_i;
        cout << "ok!" << endl;
    }

    void test_write()
    {
        ++m_i;
        cout << "ok!" << endl;
    }

    static void test_read_write_static()
    {
        int dummy = ++s_i;
        cout << "ok!" << endl;
    }

private:
    int m_i;
    static int s_i;
};

int A::s_i = 0;

int main(int argc, char * argv[], char * envp[])
{
    if (SIG_ERR == signal(SIGSEGV, sig_segv))
    {
        cout << "signal failed" << endl;
        exit(1);
    }

    A * pa = NULL;

    typedef void (A::*PFunc)(void);
    typedef pair<PFunc, const char *> Pair;
    Pair msg[3] =
    {
        make_pair
        (
            &A::test_not_access,
            "null pointer call function which donot access member:\n\t"
        ),
        make_pair
        (
            &A::test_read,
            "null pointer call function which read member:\n\t"
        ),
        make_pair
        (
            &A::test_write,
            "null pointer call function which write member:\n\t"
        )
    };

    for (int i = 0, size = sizeof(msg)/sizeof(msg[0]); i < size; ++i)
    {
        cout << msg[i].second;
        (pa->*msg[i].first)();
    }

    cout << "null pointer call static function which read and write member:\n\t";
    pa->test_read_write_static();

    return(0);
}

发现:不停地打印error!,尝试用Stevens实现的signal和signal_intr代替系统自带的signal,效果一样!调试跟踪:原来,sig_sgev处理后,程序又会回去执行刚引发SIGSGEV信号的代码... 引发死循环!



3. 利用sigsetjmp、siglongjmp处理上面的问题:

#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
#include <utility>
#include <iostream>
using namespace std;

sigjmp_buf jmpbuf;

void sig_segv(int signo)
{
    cout << "error!" << endl;
    siglongjmp(jmpbuf, 1);
}

class A
{
public:
    A() : m_i(0)
    {

    }

public:
    void test_not_access()
    {
        cout << "ok!" << endl;
    }

    void test_read()
    {
        int dummy = m_i;
        cout << "ok!" << endl;
    }

    void test_write()
    {
        ++m_i;
        cout << "ok!" << endl;
    }

    static void test_read_write_static()
    {
        int dummy = ++s_i;
        cout << "ok!" << endl;
    }

private:
    int m_i;
    static int s_i;
};

int A::s_i = 0;

int main(int argc, char * argv[], char * envp[])
{
    if (SIG_ERR == signal(SIGSEGV, sig_segv))
    {
        cout << "signal failed" << endl;
        exit(1);
    }

    A * pa = NULL;

    typedef void (A::*PFunc)(void);
    typedef pair<PFunc, const char *> Pair;
    Pair msg[3] =
    {
        make_pair
        (
            &A::test_not_access,
            "null pointer call function which donot access member:\n\t"
        ),
        make_pair
        (
            &A::test_read,
            "null pointer call function which read member:\n\t"
        ),
        make_pair
        (
            &A::test_write,
            "null pointer call function which write member:\n\t"
        )
    };

    volatile int i = 0;
    const int size = sizeof(msg)/sizeof(msg[0]);

    if (0 != sigsetjmp(jmpbuf, 1))
    {
        ++i;
    }

    for ( ; i < size; ++i)
    {
        cout << msg[i].second;
        (pa->*msg[i].first)();
    }

    cout << "null pointer call static function which read and write member:\n\t";
    pa->test_read_write_static();

    return(0);
}

现在能全部打印:

null pointer call function which donot access member:
    ok!
null pointer call function which read member:
    error!
null pointer call function which write member:
    error!
null pointer call static function which read and write member:
    ok!


4. 用多进程 fork 来做:

#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <utility>
#include <iostream>
using namespace std;

void sig_segv(int signo)
{
    cout << "error!" << endl;
    exit(0);
}

class A
{
public:
    A() : m_i(0)
    {

    }

public:
    void test_not_access()
    {
        cout << "ok!" << endl;
    }

    void test_read()
    {
        int dummy = m_i;
        cout << "ok!" << endl;
    }

    void test_write()
    {
        ++m_i;
        cout << "ok!" << endl;
    }

    static void test_read_write_static()
    {
        int dummy = ++s_i;
        cout << "ok!" << endl;
    }

private:
    int m_i;
    static int s_i;
};

int A::s_i = 0;

int main(int argc, char * argv[], char * envp[])
{
    if (SIG_ERR == signal(SIGSEGV, sig_segv))
    {
        cout << "signal failed" << endl;
        exit(1);
    }

    A * pa = NULL;

    pid_t pid = 0;

    typedef void (A::*PFunc)(void);
    typedef pair<PFunc, const char *> Pair;
    Pair msg[3] =
    {
        make_pair
        (
            &A::test_not_access,
            "null pointer call function which donot access members:\n\t"
        ),
        make_pair
        (
            &A::test_read,
            "null pointer call function which read members:\n\t"
        ),
        make_pair
        (
            &A::test_write,
            "null pointer call function which write members:\n\t"
        )
    };

    for (int i = 0, size = sizeof(msg)/sizeof(msg[0]); i < size; ++i)
    {
        if ((pid = fork()) < 0)
        {
            cout << "fork failed" << endl;
            exit(1);
        }
        else if (pid == 0)
        {
            cout << msg[i].second;
            (pa->*msg[i].first)();
            exit(0);
        }
        else
        {
            sleep(1);
        }
    }

    if ((pid = fork()) < 0)
    {
        cout << "fork failed" << endl;
        exit(1);
    }
    else if (pid == 0)
    {
        cout << "null pointer call static function which read and write member:\n\t";
        pa->test_read_write_static();
        exit(0);
    }
    else
    {
        sleep(1);
    }

    return(0);
}

也可以全部打印;当然,我们还可以用TELL_WAIT那组函数替代这里的sleep,来加快效率。


 

其实,3是在4之后想到的,因为感觉4不是太好,所以才从2中想到了3。1怎么解决呢? 是个问题!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第十一届ISQE(国际软件质量工程大会)的主角是任亮。任亮是一位软件质量工程师,他在该大会上担任主题演讲嘉宾,并分享了他在软件质量方面的研究和经验。 任亮在他的演讲中强调了软件质量的重要性以及如何提高软件质量。他指出,软件的质量不仅是指软件产品是否符合规范和要求,还包括用户体验、安全性和可靠性等方面。他强调了在软件开发过程中,确保每个环节的质量控制和测试的重要性。 任亮还分享了他在软件质量工程方面的研究成果。他介绍了一种基于机器学习的软件质量预测模型,该模型可以根据历史数据来预测软件质量问题的可能性,从而帮助开发团队采取相应的措施来改进质量。这一研究成果在业界引起了广泛的关注和讨论。 此外,任亮还分享了他在实际项目中的软件质量管理经验。他强调了持续集成、自动化测试和代码审查等实践在提高软件质量方面的重要性,并指出了一些常见软件质量问题和解决方案。 整个演讲中,任亮充分展示了他在软件质量工程领域的专业知识和经验,让参会者受益匪浅。他的演讲不仅为与会者提供了实用的软件质量管理方法和工具,也为软件质量工程领域的发展提供了新的思路和研究方向。 总之,第十一届ISQE的主角任亮通过他的演讲为软件质量工程领域做出了积极贡献,他的研究成果和实践经验对于提高软件质量具有重要意义,也激发了人们对软件质量工程的深入思考和研究。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值