• Re: 首都航空JD5759航班的情况

    最近事故真多

    【 在 i3721pp (12个马拉松,11个相机) 的大作中提到: 】

    http://www.minhangshi.com/m/h5/online/4935071

    : 民航事 直播员 2018-08-28 14:06

    : 气象报文显示澳门落地时间前后有雷雨,风向不定风速15kt,阵风25kt。风切变,简单理解就是风向和/或风速突然急剧变化。飞机须要相对空气存在一定速度才能飞行,如果瞬间出现大顺风,会造成飞机相对空气速度突然变小,升力急剧下降,导致提前或超重接地。就好比你在游泳

    2018-08-28
  • Re: 有没有逆向regular expression的模块?

    当然没有唯一解了

    比如

    .*

    (expr1|expr2|...|exprN)

    就是两个解

    【 在 damekko (damekko) 的大作中提到: 】

    : 感觉这个问题不能有唯一解

    2018-08-28
  • Re: 牛娇精选(四四七)zz

    【 在 kissonline (牛姐姐) 的大作中提到: 】

    : 1

    : 作为单身狗,我找了个人临时凑个伴,一起过一个假的七夕情人节,简称拼夕夕。

    : 2

    : ...................

    2018-08-20
  • Re: vector和list要不要加个operator<<

    我现在用boost的assign

    【 在 lwp (Library for WWW access in Perl) 的大作中提到: 】

    : 感觉Qt的这个operator重载后很好用,一次添加多个

    2018-08-05
  • [合集] [请教]刚找了一个工作,入职前想提前准备下相关知识

    ☆─────────────────────────────────────☆

     qiaoqiao0123 (qiaoqiao0123) 于  (Thu Jun  8 14:23:17 2017)  提到:

    想进去时尽早上手。

    一个软件公司cloud部门,进去做Security,Oauth相关的开发和测试。

    其实我没有cloud的经验,我想问下,我应该准备那些知识和编程语言。

    java需要吗?或者js?

    面试了C++和python。

    非常感谢!

    ☆─────────────────────────────────────☆

     dpblue (deep blue) 于  (Fri Jun  9 12:21:36 2017)  提到:

    你可以给面试官或HR发个邮件,问问需要准备什么知识,他们应该会很乐意回答你这个问题的

    ☆─────────────────────────────────────☆

     qiaoqiao0123 (qiaoqiao0123) 于  (Fri Jun  9 13:50:28 2017)  提到:

    谢谢!

    【 在 dpblue 的大作中提到: 】

    : 你可以给面试官或HR发个邮件,问问需要准备什么知识,他们应该会很乐意回答你这个问题的

    2017-06-21
  • Re: 结婚了,送礼物了! (转载)

    恭喜恭喜

    【 在 ygxz (迎桂轩主|真性圆觉,仁慈博爱,忍而不自弃) 的大作中提到: 】

    : 【 以下文字转载自 Shandong 讨论区 】

    : 发信人: ygxz (迎桂轩主|真性圆觉,仁慈博爱,忍而不自弃), 信区: Shandong

    : 标  题: 结婚了,送礼物了!

    : ...................

    2017-05-30
  • Re:为什么会跳过代码不执行呢

    看不懂

    【 在 scanworld 的大作中提到: 】

    :在做点云拼接的工作,只是导入两张图片,然后转换成点云再拼接

    :拼接过程有一个voxel滤波器 旧点云和新点云连接都没问题

    :一定义一个滤波器的输出变量就会自动跳过这个声明

    :...................

    2017-05-28
  • Re:两个cpp参考网站哪个好

    内容都差不多,随意

    【 在 typo 的大作中提到: 】

    :有什么区别,各有什么优势?

    :http://www.cplusplus.com http://en.cppreference.com

    :--

    :...................

    2017-05-24
  • [合集] 这么多模板高手在此,问一个我一直没想清楚怎么做的问题

    ☆─────────────────────────────────────☆

     here080 (hero080) 于  (Tue Nov 17 06:09:50 2015)  提到:

    template <typename T>

    void Foo(const std::unordered_map<string, T>& m);

    如何同时给出:

    1. 一般性的实现

    2. 如果T是类Base派生出来的,就用另外一种实现。

    ☆─────────────────────────────────────☆

     youxia (游侠) 于  (Tue Nov 17 06:21:21 2015)  提到:

    模版特化

    ☆─────────────────────────────────────☆

     here080 (hero080) 于  (Tue Nov 17 06:21:50 2015)  提到:

    怎么弄?

    【 在 youxia (游侠) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     youxia (游侠) 于  (Tue Nov 17 06:24:31 2015)  提到:

    百度下,很简单

    【 在 here080 的大作中提到: 】

    ☆─────────────────────────────────────☆

     javaboy (喝了咖啡就话多-_-;) 于  (Tue Nov 17 06:31:20 2015)  提到:

    【 在 here080 (hero080) 的大作中提到: 】

    , enable_if<is_base_of<Base,T>>::type *=0

    (Edit:少了一个::value)

    如是派生的,则展开成 void Foo(map&, void* = 0),调用时可省略第二个参数。

    不是派生的,则SFINAE,定义无效。

    ☆─────────────────────────────────────☆

     here080 (hero080) 于  (Tue Nov 17 06:33:24 2015)  提到:

    这样不是就让一般定义也无效了吗?

    【 在 javaboy (喝了咖啡就话多-_-;) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     javaboy (喝了咖啡就话多-_-;) 于  (Tue Nov 17 06:36:21 2015)  提到:

    可以再写一个一样signature的函数,只把enable_if换成disable_if。

    【 在 here080 (hero080) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     here080 (hero080) 于  (Tue Nov 17 06:36:41 2015)  提到:

    我搜过了。我试过enable_if,没有成功。

    【 在 youxia (游侠) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     youxia (游侠) 于  (Tue Nov 17 07:02:54 2015)  提到:

    重新定义一个模版,只是其typename T 改成你需要特例化的类型

    【 在 here080 的大作中提到: 】

    ☆─────────────────────────────────────☆

     here080 (hero080) 于  (Tue Nov 17 07:13:05 2015)  提到:

    需要特例化的是很多个子类啊。

    【 在 youxia (游侠) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     here080 (hero080) 于  (Tue Nov 17 07:36:08 2015)  提到:

    真的可以吗?我是把enable_if放在返回值的:

    代码:

    =================================================

    #include <iostream>

    #include <vector>

    using std::string;

    using std::vector;

    class A;

    template <typename T>

    void Foo(const vector<T>& v);

    template <typename T>

    typename std::enable_if<std::is_base_of<A, T>::value>::type

    Foo(const vector<T>& v) {

    std::cout << "special." << std::endl;

    }

    template <typename T>

    typename std::enable_if<!std::is_base_of<A, T>::value>::type

    Foo(const vector<T>& v) {

    std::cout << "general." << std::endl;

    }

    class A {};

    class B : public A {};

    int main() {

    std::cout << "hello" << std::endl;

    vector<int> v_int = {1, 2, 3};

    vector<B> v_b;

    Foo(v_int);

    Foo(v_b);

    return 0;

    }

    ==============================================

    g++ 5.2.0 编译错误:

    $ g++ -o abc -std=c++11 abc.cc

    abc.cc: 在函数‘int main()’中:

    abc.cc:31:12: 错误:调用重载的‘Foo(std::vector<int>&)’有歧义

    Foo(v_int);

    ^

    abc.cc:10:6: 附注:candidate: void Foo(const std::vector<T>&) [with T = int]

    void Foo(const vector<T>& v);

    ^

    abc.cc:20:1: 附注:candidate: typename std::enable_if<(! std::is_base_of<A, T>::value)>::type Foo(const std::vector<T>&) [with T = int; typename std::enable_if<(! std::is_base_of<A, T>::value)>::type = void]

    Foo(const vector<T>& v) {

    ^

    abc.cc:32:10: 错误:调用重载的‘Foo(std::vector<B>&)’有歧义

    Foo(v_b);

    ^

    abc.cc:10:6: 附注:candidate: void Foo(const std::vector<T>&) [with T = B]

    void Foo(const vector<T>& v);

    ^

    abc.cc:14:1: 附注:candidate: typename std::enable_if<std::is_base_of<A, T>::value>::type Foo(const std::vector<T>&) [with T = B; typename std::enable_if<std::is_base_of<A, T>::value>::type = void]

    Foo(const vector<T>& v) {

    ^

    【 在 javaboy (喝了咖啡就话多-_-;) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     youxia (游侠) 于  (Tue Nov 17 07:47:47 2015)  提到:

    你再派生一个子类childALL,所有的需要特例化的子类都继承自它。

    然后对childALL特例化即可

    【 在 here080 的大作中提到: 】

    ☆─────────────────────────────────────☆

     here080 (hero080) 于  (Tue Nov 17 07:51:52 2015)  提到:

    我没懂你的意思。

    首先,显然子类父类关系是现成的(我最初碰到这个问题时,对应的情况是有几十万个子类),没有道理去修改。

    就算先不管这个,派生出一个子类childAll然后对childAll特例化,跟直接对Base特例化有什么区别?

    【 在 youxia (游侠) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     youxia (游侠) 于  (Tue Nov 17 08:22:14 2015)  提到:

    我理解错了,应该是直接特例化Base即可。

    【 在 here080 的大作中提到: 】

    ☆─────────────────────────────────────☆

     XeCycle (据说是小 X) 于  (Tue Nov 17 08:33:33 2015)  提到:

    tag dispatch

    【 在 here080 (hero080) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     XeCycle (据说是小 X) 于  (Tue Nov 17 08:38:02 2015)  提到:

    Foo_impl(const map& m, std::true_type /* is derived from Base */);

    Foo_impl(const map& m, std::false_type /* not derived from Base */);

    Foo(const map& m) { return Foo_impl(m, std::is_base_of<Base, T>); }

    【 在 XeCycle (据说是小 X) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     xiaoju (可爱的龙猫) 于  (Tue Nov 17 08:49:05 2015)  提到:

    翻翻MS的ATL和WTL的代码,里面不少这种东西。

    【 在 here080 (hero080) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     adda (adda) 于  (Tue Nov 17 09:12:17 2015)  提到:

    #include<iostream>

    #include<map>

    #include<string>

    using namespace std;

    class Base1 {};

    class Derived1 :public Base1 {};

    class Base2 {};

    class Derived2 :public Base2 {};

    template<typename T>

    void _FooImpl(const map<string, T>& m, ...)        // 一般实现

    {

    cout << "General Implement" << endl;

    }

    template<typename T>

    void _FooImpl(const map<string, T>& m, typename T::Base1*)    // T是Base1及其子类

    {

    cout << "Specialized Implement1" << endl;

    }

    template<typename T>

    void _FooImpl(const map<string, T>& m, typename T::Base2*)    // T是Base2及其子类

    {

    cout << "Specialized Implement2" << endl;

    }

    template<typename T>

    void Foo(const map<string, T>& m)

    {

    _FooImpl(m, nullptr);

    }

    int main()

    {

    map<string, int> map1;

    map<string, Derived1> map2;

    map<string, Base2> map3;

    Foo(map1);

    Foo(map2);

    Foo(map3);

    }

    【 在 here080 的大作中提到: 】

    ☆─────────────────────────────────────☆

     here080 (hero080) 于  (Tue Nov 17 09:48:41 2015)  提到:

    原来如此,看起来很不错

    【 在 XeCycle (据说是小 X) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     here080 (hero080) 于  (Tue Nov 17 09:49:19 2015)  提到:

    这个更好,能解决多个特例的情况。

    【 在 adda (adda) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     vonNeumann (劣币驱逐良币 | 少灌水) 于  (Tue Nov 17 12:58:28 2015)  提到:

    以后用 C++17 就非常简单了,都不需要什么技巧,用 concept,直接这样写:

    template <typename T> requires std::is_base_of<Base, T>::value

    void Foo(const map<string, T>& m) {

    }

    template <typename T> requires !std::is_base_of<Base, T>::value

    void Foo(const map<string, T>& m) {

    }

    【 在 here080 (hero080) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     youxia (游侠) 于  (Tue Nov 17 14:40:22 2015)  提到:

    C++17什么时候可用?

    【 在 vonNeumann 的大作中提到: 】

    ☆─────────────────────────────────────☆

     javaboy (喝了咖啡就话多-_-;) 于  (Tue Nov 17 14:59:11 2015)  提到:

    当然可以。

    你的前置声明写错了。

    【 在 here080 (hero080) 的大作中提到: 】

    void Foo(const T& any_vector);

    修改后的运行结果:

    hello

    general.

    special.

    ☆─────────────────────────────────────☆

     javaboy (喝了咖啡就话多-_-;) 于  (Tue Nov 17 15:07:18 2015)  提到:

    冯大师太强了。。每次都忍不住瞻仰下。

    【 在 vonNeumann (劣币驱逐良币 | 少灌水) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     vonNeumann (劣币驱逐良币 | 少灌水) 于  (Tue Nov 17 22:08:41 2015)  提到:

    不知道,因为现在才 2015 年。。

    不过上面这个特性 gcc 的 trunk 版本已经实现了,明年 gcc 6 就有

    【 在 youxia (游侠) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     acalism (节制,沉静,有序) 于  (Tue Nov 17 23:30:42 2015)  提到:

    瞻仰!!!

    【 在 vonNeumann (劣币驱逐良币 | 少灌水) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     here080 (hero080) 于  (Thu Nov 19 16:35:38 2015)  提到:

    这可奇怪了。为什么不能写成准确的前置声明?

    【 在 javaboy (喝了咖啡就话多-_-;) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     libgcc (五年内不再bg了) 于  (Thu Nov 19 17:25:59 2015)  提到:

    我去明年gcc就6了?

    【 在 vonNeumann (劣币驱逐良币 | 少灌水) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     vonNeumann (劣币驱逐良币 | 少灌水) 于  (Thu Nov 19 17:38:39 2015)  提到:

    是。

    gcc x.y.z

    以前是每年 y++

    现在改成了每年 x++

    【 在 libgcc (五年内不再bg了) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     here080 (hero080) 于  (Fri Nov 20 03:03:12 2015)  提到:

    我需要的东西,核心难点就是存在一个CONTAINER

    否则的话直接对Base做SPECIALIZATION就行了。

    Foo(const Base& t)是可以直接用在所有子类上的。.

    另外,把enable_if用在返回值上,是不会影响函数签名的。enable_if是可以指定类型的。

    【 在 ble (ble) 的大作中提到: 】

    【 在 here080 的大作中提到: 】

    : template <typename T>

    : void Foo(const std::unordered_map<string, T>& m);

    : 如何同时给出:

    : ...................

    : 标  题: Re: 这么多模板高手在此,问一个我一直没想清楚怎么做的问题

    : 发信站: 水木社区 (Tue Nov 17 06:21:21 2015), 站内

    : 模版特化

    : 【 在 here080 的大作中提到: 】

    : : template <typename T>

    : : void Foo(const std::unordered_map<string, T>& m);

    : : 如何同时给出:

    : : ...................

    : --

    : 怎么弄?

    : template <typename T>

    : void Foo(const std::unordered_map<string, T>& m                );

    : 如何同时给出:

    : 1. 一般性的实现

    : 2. 如果T是类Base派生出来的,就用另外一种实现。

    :                                                  , enable_if<is_base_of<Base,T>>::type *=0

    : 如是派生的,则展开成 void Foo(map&, void* = 0),调用时可省略第二个参数。

    : 不是派生的,则SFINAE,定义无效。

    : ...................

    : 这样不是就让一般定义也无效了吗?

    : 标  题: Re: 这么多模板高手在此,问一个我一直没想清楚怎么做的问题

    : 发信站: 水木社区 (Tue Nov 17 06:24:31 2015), 站内

    : 百度下,很简单

    : 【 在 here080 的大作中提到: 】

    : : 怎么弄?

    : :

    : --

    : 我搜过了。我试过enable_if,没有成功。

    : 标  题: Re: 这么多模板高手在此,问一个我一直没想清楚怎么做的问题

    : 发信站: 水木社区 (Tue Nov 17 07:02:54 2015), 站内

    : 重新定义一个模版,只是其typename T 改成你需要特例化的类型

    : 【 在 here080 的大作中提到: 】

    : : 我搜过了。我试过enable_if,没有成功。

    : :

    : --

    : 标  题: Re: 这么多模板高手在此,问一个我一直没想清楚怎么做的问题

    : 发信站: 水木社区 (Tue Nov 17 06:36:21 2015), 站内

    : 可以再写一个一样signature的函数,只把enable_if换成disable_if。

    : 【 在 here080 (hero080) 的大作中提到: 】

    : : 这样不是就让一般定义也无效了吗?

    : --

    : Can't go back to where I used to be.

    : 需要特例化的是很多个子类啊。

    : 标  题: Re: 这么多模板高手在此,问一个我一直没想清楚怎么做的问题

    : 发信站: 水木社区 (Tue Nov 17 07:47:47 2015), 站内

    : 你再派生一个子类childALL,所有的需要特例化的子类都继承自它。

    : 然后对childALL特例化即可

    : 【 在 here080 的大作中提到: 】

    : : 需要特例化的是很多个子类啊。

    : :

    : --

    : 我没懂你的意思。

    : 首先,显然子类父类关系是现成的(我最初碰到这个问题时,对应的情况是有几十万个子类),没有道理去修改。

    : 就算先不管这个,派生出一个子类childAll然后对childAll特例化,跟直接对Base特例化有什么区别?

    : ...................

    : template <typename T>

    : void Foo(const std::unordered_map<string, T>& m);

    : 如何同时给出:

    : ...................

    : tag dispatch

    : template <typename T>

    : void Foo(const std::unordered_map<string, T>& m);

    : 如何同时给出:

    : ...................

    : template <typename T>

    : void Foo(const std::unordered_map<string, T>& m);

    : 如何同时给出:

    : ...................

    : 标  题: Re: 这么多模板高手在此,问一个我一直没想清楚怎么做的问题

    : 发信站: 水木社区 (Tue Nov 17 08:38:02 2015), 站内

    : Foo_impl(const map& m, std::true_type /* is derived from Base */);

    : Foo_impl(const map& m, std::false_type /* not derived from Base */);

    : Foo(const map& m) { return Foo_impl(m, std::is_base_of<Base, T>); }

    : 【 在 XeCycle (据说是小 X) 的大作中提到: 】

    : : tag dispatch

    : --

    : 标  题: Re: 这么多模板高手在此,问一个我一直没想清楚怎么做的问题

    : 发信站: 水木社区 (Tue Nov 17 09:12:17 2015), 站内

    : #include<iostream>

    : #include<map>

    : #include<string>

    : using namespace std;

    : class Base1 {};

    : class Derived1 :public Base1 {};

    : class Base2 {};

    : class Derived2 :public Base2 {};

    : template<typename T>

    : void _FooImpl(const map<string, T>& m, ...)        // 一般实现

    : {

    :     cout << "General Implement" << endl;

    : }

    : template<typename T>

    : void _FooImpl(const map<string, T>& m, typename T::Base1*)    // T是Base1及其子类

    : {

    :     cout << "Specialized Implement1" << endl;

    : }

    : template<typename T>

    : void _FooImpl(const map<string, T>& m, typename T::Base2*)    // T是Base2及其子类

    : {

    :     cout << "Specialized Implement2" << endl;

    : }

    : template<typename T>

    : void Foo(const map<string, T>& m)

    : {

    :     _FooImpl(m, nullptr);

    : }

    : int main()

    : {

    :     map<string, int> map1;

    :     map<string, Derived1> map2;

    :     map<string, Base2> map3;

    :     Foo(map1);

    :     Foo(map2);

    :     Foo(map3);

    : }

    : 【 在 here080 的大作中提到: 】

    : : template <typename T>

    : : void Foo(const std::unordered_map<string, T>& m);

    : : 如何同时给出:

    : : ...................

    : --

    : 这个更好,能解决多个特例的情况。

    : 以后用 C++17 就非常简单了,都不需要什么技巧,用 concept,直接这样写:

    : template <typename T> requires std::is_base_of<Base, T>::value

    : void Foo(const map<string, T>& m) {

    : ...................

    : 真的可以吗?我是把enable_if放在返回值的:

    : 代码:

    : =================================================

    : #include <iostream>

    : #include <vector>

    : using std::string;

    : using std::vector;

    : class A;

    : template <typename T>

    : void Foo(const vector<T>& v);

    : template <typename T>

    : typename std::enable_if<std::is_base_of<A, T>::value>::type

    : Foo(const vector<T>& v) {

    :   std::cout << "special." << std::endl;

    : }

    : template <typename T>

    : typename std::enable_if<!std::is_base_of<A, T>::value>::type

    : Foo(const vector<T>& v) {

    :   std::cout << "general." << std::endl;

    : }

    : class A {};

    : class B : public A {};

    : int main() {

    :   std::cout << "hello" << std::endl;

    :   vector<int> v_int = {1, 2, 3};

    :   vector<B> v_b;

    :   Foo(v_int);

    :   Foo(v_b);

    :   return 0;

    : }

    : ==============================================

    : g++ 5.2.0 编译错误:

    : $ g++ -o abc -std=c++11 abc.cc

    : abc.cc: 在函数‘int main()’中:

    : abc.cc:31:12: 错误:调用重载的‘Foo(std::vector<int>&)’有歧义

    :    Foo(v_int);

    :             ^

    : abc.cc:10:6: 附注:candidate: void Foo(const std::vector<T>&) [with T = int]

    :  void Foo(const vector<T>& v);

    :       ^

    : abc.cc:20:1: 附注:candidate: typename std::enable_if<(! std::is_base_of<A, T>::value)>::type Foo(const std::vector<T>&) [with T = int; typename std::enable_if<(! std::is_base_of<A, T>::value)>::type = void]

    :  Foo(const vector<T>& v) {

    :  ^

    : abc.cc:32:10: 错误:调用重载的‘Foo(std::vector<B>&)’有歧义

    :    Foo(v_b);

    :           ^

    : abc.cc:10:6: 附注:candidate: void Foo(const std::vector<T>&) [with T = B]

    :  void Foo(const vector<T>& v);

    :       ^

    : abc.cc:14:1: 附注:candidate: typename std::enable_if<std::is_base_of<A, T>::value>::type Foo(const std::vector<T>&) [with T = B; typename std::enable_if<std::is_base_of<A, T>::value>::type = void]

    :  Foo(const vector<T>& v) {

    :  ^

    : 以后用 C++17 就非常简单了,都不需要什么技巧,用 concept,直接这样写:

    : template <typename T> requires std::is_base_of<Base, T>::value

    : void Foo(const map<string, T>& m) {

    : }

    : template <typename T> requires !std::is_base_of<Base, T>::value

    : void Foo(const map<string, T>& m) {

    : }

    : C++17什么时候可用?

    : 标  题: Re: 这么多模板高手在此,问一个我一直没想清楚怎么做的问题

    : 发信站: 水木社区 (Tue Nov 17 12:58:28 2015), 站内

    : 以后用 C++17 就非常简单了,都不需要什么技巧,用 concept,直接这样写:

    : template <typename T> requires std::is_base_of<Base, T>::value

    : void Foo(const map<string, T>& m) {

    : }

    : template <typename T> requires !std::is_base_of<Base, T>::value

    : void Foo(const map<string, T>& m) {

    : }

    : 【 在 here080 (hero080) 的大作中提到: 】

    : : 这个更好,能解决多个特例的情况。

    : --

    : GFDSA  HJKLM  TREWQ  YUIOP  NBVCX

    : 王土大木工  目日口田山  禾白月人金  言立水火之  已子女又纟

    : 一地在要工  上是中国同  和的有人我  主产不为这  民了发以经

    : 标  题: Re: 这么多模板高手在此,问一个我一直没想清楚怎么做的问题

    : 发信站: 水木社区 (Tue Nov 17 14:59:11 2015), 站内

    : 当然可以。

    : 你的前置声明写错了。

    : 【 在 here080 (hero080) 的大作中提到: 】

    : : 真的可以吗?我是把enable_if放在返回值的:

    : : 代码:

    : : =================================================

    : : #include <iostream>

    : : #include <vector>

    : : using std::string;

    : : using std::vector;

    : : class A;

    : : template <typename T>

    : : void Foo(const vector<T>& v);

    :   void Foo(const T& any_vector);

    : 修改后的运行结果:

    : hello

    : general.

    : special.

    : : template <typename T>

    : : typename std::enable_if<std::is_base_of<A, T>::value>::type

    : : Foo(const vector<T>& v) {

    : :   std::cout << "special." << std::endl;

    : : }

    : : template <typename T>

    : : typename std::enable_if<!std::is_base_of<A, T>::value>::type

    : : Foo(const vector<T>& v) {

    : :   std::cout << "general." << std::endl;

    : : }

    : : class A {};

    : : class B : public A {};

    : : int main() {

    : :   std::cout << "hello" << std::endl;

    : :   vector<int> v_int = {1, 2, 3};

    : :   vector<B> v_b;

    : :   Foo(v_int);

    : :   Foo(v_b);

    : :   return 0;

    : : }

    : : ==============================================

    : : g++ 5.2.0 编译错误:

    : : $ g++ -o abc -std=c++11 abc.cc

    : : abc.cc: 在函数‘int main()’中:

    : : abc.cc:31:12: 错误:调用重载的‘Foo(std::vector<int>&)’有歧义

    : :    Foo(v_int);

    : :             ^

    : : abc.cc:10:6: 附注:candidate: void Foo(const std::vector<T>&) [with T = int]

    : :  void Foo(const vector<T>& v);

    : :       ^

    : : abc.cc:20:1: 附注:candidate: typename std::enable_if<(! std::is_base_of<A, T>::value)>::type Foo(const std::vector<T>&) [with T = int; typename std::enable_if<(! std::is_base_of<A, T>::value)>::type = void]

    : :  Foo(const vector<T>& v) {

    : :  ^

    : : abc.cc:32:10: 错误:调用重载的‘Foo(std::vector<B>&)’有歧义

    : :    Foo(v_b);

    : :           ^

    : : abc.cc:10:6: 附注:candidate: void Foo(const std::vector<T>&) [with T = B]

    : :  void Foo(const vector<T>& v);

    : :       ^

    : : abc.cc:14:1: 附注:candidate: typename std::enable_if<std::is_base_of<A, T>::value>::type Foo(const std::vector<T>&) [with T = B; typename std::enable_if<std::is_base_of<A, T>::value>::type = void]

    : :  Foo(const vector<T>& v) {

    : :  ^

    : --

    : Can't go back to where I used to be.

    : 不知道,因为现在才 2015 年。。

    : 不过上面这个特性 gcc 的 trunk 版本已经实现了,明年 gcc 6 就有

    : 我去明年gcc就6了?

    : 标  题: Re: 这么多模板高手在此,问一个我一直没想清楚怎么做的问题

    : 发信站: 水木社区 (Tue Nov 17 22:49:02 2015), 站内

    : 你这个是靠返回值区分,还有函数参数的,这些都影响函数签名。

    : 感觉还是模版参数的最好,正好今天写了一个:

    : 缺省的

    : template<typename T,

    :          typename Default = void>

    : int Calc(const T& t);

    : 针对Base派生类的偏特化

    : template<typename T,

    :          typename std::enable_if<

    :            std::is_base_of<T, Base>::value

    :          >::type* = nullptr>

    : int Calc(const T& t);

    : 【 在 here080 (hero080) 的大作中提到: 】

    : : 真的可以吗?我是把enable_if放在返回值的:

    : : 代码:

    : : =================================================

    : : ...................

    : --

    2017-05-19
  • [合集] std::thread竟然不自带判断线程是否结束的功能?

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Mon May  8 11:34:42 2017)  提到:

    本来以为joinable可以判断

    但仔细看了看说明,发现其实不行,这个函数其实没有存在的必要。

    ☆─────────────────────────────────────☆

     blitz (blitz) 于  (Mon May  8 13:00:17 2017)  提到:

    我记得一个已经开始的进程,如果不被deatch,不被join,那么它在结束之前都是joinable的

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Mon May  8 13:04:37 2017)  提到:

    问题是在结束之后、join之前,它也是joinable的!

    【 在 blitz @ [CPlusPlus] 的大作中提到: 】

    ☆─────────────────────────────────────☆

     shallowreg (金子) 于  (Mon May  8 13:08:38 2017)  提到:

    【 在 origin008 的大作中提到: 】

    pthread_join也不是这样设计的吗? 有什么问题?

    ☆─────────────────────────────────────☆

     blitz (blitz) 于  (Mon May  8 13:09:39 2017)  提到:

    那就join一下被,如果结束了,join就立马返回了啊

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Mon May  8 14:29:06 2017)  提到:

    join是阻塞的啊

    我的目标是这样:

    主线程:

    *     启动工作线程

    *     循环:

    *            干循环的活

    *            工作线程完成了吗?

    *            完成了:退出循环,

    *            否则:继续

    【 在 blitz @ [CPlusPlus] 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Mon May  8 14:29:49 2017)  提到:

    问题就是帖子标题啊!

    怎么判断线程是否结束?

    【 在 shallowreg @ [CPlusPlus] 的大作中提到: 】

    ☆─────────────────────────────────────☆

     poikilotherm (呆子) 于  (Mon May  8 14:46:14 2017)  提到:

    你这是在启动的工作线程判断工作是否完成?

    【 在 origin008 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Mon May  8 15:57:18 2017)  提到:

    是啊

    主线程启动工作线程,然后循环接收用户命令、判断是否结束工作线程。如果工作线程自己结束,就主程序也退出。

    这应该是比较典型的模式吧?

    然而就卡在了如何判断工作线程是否结束的问题上。

    当然,自行设置一个变量可以,但理解不了为何thread类没这个功能。

    【 在 poikilotherm 的大作中提到: 】

    ☆─────────────────────────────────────☆

     kobe2000 (WebWheel@GitHub) 于  (Mon May  8 16:28:41 2017)  提到:

    因为大多数线程不需要知道是否结束

    【 在 origin008 的大作中提到: 】

    ☆─────────────────────────────────────☆

     poikilotherm (呆子) 于  (Mon May  8 17:27:18 2017)  提到:

    你启动工作线程后,join工作线程,任务完成了线程自己就会退出。看你的说法,你判断线程是否结束,也不做别的事情啊,不明白你这个设计的目的是什么?

    【 在 origin008 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Gameplayer (*.*) 于  (Mon May  8 17:43:43 2017)  提到:

    要是能用pthread,可以试试pthread_tryjoin_np,好像能满足你的要求

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     ziqin (子青|会挽雕弓如满月|西北望|射天狼) 于  (Mon May  8 18:02:11 2017)  提到:

    线程的任务是否完成和线程是否joinable是两个逻辑

    层面的东西。

    线程是否joinable是更底层的逻辑,在这层逻辑是系

    统关心的,各种内存释放的破事。

    任务是否完成,是你任务函数的逻辑层面,这是比

    joinable更高一层的逻辑。

    逻辑分层去耦合,这是最基本的框架思路。如果你希望

    有一个地方可以检测任务是否完成,你应该在你的任务

    函数里放一个flag或者conditioanl variable之

    类的东西。

    好好学逻辑学吧,别没事乱喷

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Mon May  8 18:23:21 2017)  提到:

    还真没学过逻辑学

    推荐本教材吧?

    【 在 ziqin @ [CPlusPlus] 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Mon May  8 18:25:39 2017)  提到:

    最简单的例子,

    启动工作线程后等待接收用户的输入,

    用户如果命令退出,就提前结束返回

    工作线程如果结束了,主线程也要结束返回。

    就是这么个逻辑,真的不符合逻辑学吗?

    【 在 poikilotherm @ [CPlusPlus] 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Mon May  8 18:57:01 2017)  提到:

    除了逻辑学教材外,还有两个问题要请教:

    1、joinable函数对于thread类的使用者而言,有什么作用?thread类的设计者为什么要对用户开放这个函数?

    2、thread类的设计者提供一个低层次的joinable函数,而不提供一个更高层次的判断线程是否运行结束的判断函数,是出于什么考虑呢?

    请大神不吝赐教,谢谢!

    【 在 ziqin 的大作中提到: 】

    ☆─────────────────────────────────────☆

     shallowreg (金子) 于  (Mon May  8 19:45:16 2017)  提到:

    【 在 origin008 的大作中提到: 】

    0. 和逻辑学没关系,是程序设计逻辑

    1. 直接按功能来理解作用,阻塞或者不符合你需求不代表没有价值

    2. 现有的为什么做不到?

    ☆─────────────────────────────────────☆

     poikilotherm (呆子) 于  (Mon May  8 21:13:12 2017)  提到:

    你这不就是想根据用户指令终止工作线程吗? 最简单的办法设置一个flag,在工作线程判断flag退出线程不就得了?

    这个简单的一个功能,你喷人家thread至于么?

    【 在 origin008 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Mon May  8 22:19:13 2017)  提到:

    为什么不能喷呢?

    我觉得这个判断线程函数是否运行完毕的功能经常会用到,thread类设计者为什么不提供呢?

    提供的那个joinable函数,对thread类的用户而言又有什么作用呢?

    【 在 poikilotherm @ [CPlusPlus] 的大作中提到: 】

    ☆─────────────────────────────────────☆

     DoorWay (DoorWay) 于  (Mon May  8 22:38:59 2017)  提到:

    高层次的是: thread.isRunning 吧。 QThread 有。顺着这个思路搜了一下:

    https://codedump.io/share/tj0sUKbrspev/1/how-to-check-if-a-stdthread-is-still-running

    1 用 auto future = std::async(work_fun); auto status = future.wait_for(...); // status == ready 意味着已经结束

    2 用 std::promise<T> p;  将 p 传进thread. 利用p.future,查询状态。

    3 设置一个 flag, which is more simpler...

    ps: 感觉你有完美倾向。 其实别把线程想得太神秘太冰清玉洁,用 flag 没有不优雅。 线程能存在的原因,

    恰恰是因为在其能与主线程,共享虚拟内存空间,即,共享变量。所有讲线程的书上,都会提一句“比进程

    开销小”。

    ☆─────────────────────────────────────☆

     poikilotherm (呆子) 于  (Mon May  8 22:40:24 2017)  提到:

    你有没有想过,假如给你提供这个接口,你要怎么用?如果你判断到线程还在运行,你接下来怎么办?循环去判断直到运行结束?

    【 在 origin008 () 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Mon May  8 22:57:41 2017)  提到:

    谢谢!受教了!

    【 在 DoorWay 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Mon May  8 23:07:24 2017)  提到:

    很简单啊,比如:

    void foo(bool* p)

    {

    bool &quit = *p;

    // lengthy work

    bool done = false;

    while (!quit && !done) {

    // ...

    }

    return;

    }

    int main(int argc, char* argv[])

    {

    bool quit = false;

    // init work

    // ...

    std::thread work_thread(foo, &quit);

    // check user command and thread state

    while (true) {

    if (work_thread.is_dead()) break;

    if (peek_input() == 'q') break;

    // ...

    }

    // clean work

    quit = true;

    work_thread.join();

    // ...

    return 0;

    }

    【 在 poikilotherm 的大作中提到: 】

    ☆─────────────────────────────────────☆

     poikilotherm (呆子) 于  (Mon May  8 23:45:17 2017)  提到:

    你的peek_input()在用户没有输入的时候不会阻塞main thread?

    【 在 origin008 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Mon May  8 23:54:02 2017)  提到:

    因为他是PEEK,所以不阻塞

    【 在 poikilotherm 的大作中提到: 】

    ☆─────────────────────────────────────☆

     poikilotherm (呆子) 于  (Tue May  9 00:34:16 2017)  提到:

    future/promise

    【 在 origin008 的大作中提到: 】

    ☆─────────────────────────────────────☆

     mldonkey (驴) 于  (Tue May  9 15:18:53 2017)  提到:

    还没有setname呢

    标准库要兼顾兼容通用扩展性和效率

    功能少一点是可以理解的

    留给其他库去扩展

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     ysheshang (<map and target>) 于  (Wed May 10 10:02:36 2017)  提到:

    这个可能是楼主需要的

    c11的thread用的时候确实和之前不大一样,人家的理念就是让你面向任务,底层的事情交给他们吧

    async让我不爽的是,如果我的任务就是没有返回呢

    【 在 DoorWay (DoorWay) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     poikilotherm (呆子) 于  (Wed May 10 11:46:18 2017)  提到:

    没有返回值就让新线程一边去干它自己活,自己干完了销毁得了

    【 在 ysheshang 的大作中提到: 】

    ☆─────────────────────────────────────☆

     ziqin (子青|会挽雕弓如满月|西北望|射天狼) 于  (Wed May 10 15:04:32 2017)  提到:

    还是做伸手党 我前面一个帖子已经把你需要去思考的

    东西说得很清楚了。

    你在本质上没有区分thread和task两个东西,这两个

    是两个逻辑层面的东西。

    thread是系统关心的,涉及的是context

    switching等破事,joinable的目的就是告诉系统

    怎么处理这些破事。

    task是你具体在某个thread里做的事,怎么通知程序

    其他部分task的状态是task的事。

    如果在thread层面就涉及task的逻辑,比如task有

    没有结束,那代码和构架必然会有很大的耦合性。比如

    task是否结束是采用轮训机制还是通知机制,是系统

    通知还是代码通知,是否要线程安全等等破事。

    并行编程的趋势就是在逻辑上分离并行逻辑和编程逻

    辑,这样无论是多线程还是多进程还是服务器集群还是

    你们现在所谓的mapreduce都不用修改太多上层构

    架,就这点来说 c++11里的future/promise是对

    pthread的一大飞跃。

    伸手党看再多的书都没用!

    【 在 origin008 (Origin) 的大作中提到: 】

    有什么作用?thread类的设计者为什么要对用户开放

    这个函数?

    joinable函数,而不提供一个更高层次的判断线程是

    否运行结束的判断函数,是出于什么考虑呢?

    ☆─────────────────────────────────────☆

     ilovecpp (cpp) 于  (Wed May 10 15:29:24 2017)  提到:

    最早的提案是有try_join的,后面不知为何删掉了。

    std::thread不好用就用别的线程库好了。线程本身不太出现在第三方库接口上,和UI一样标准化必要性相对较低,特别是C++标准这种找所有平台最大公约数的标准化,对线程库来说特别难以接受。

    【 在 DoorWay 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Wed May 10 21:35:39 2017)  提到:

    您训斥得很对,

    但我却听不懂。

    听得懂的版友请举手!

    【 在 ziqin @ [CPlusPlus] 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Thu May 11 01:29:43 2017)  提到:

    谦虚使人进步

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     poikilotherm (呆子) 于  (Thu May 11 01:39:50 2017)  提到:

    听不懂就多看书学习

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     littleSram (littleSram) 于  (Thu May 11 06:02:21 2017)  提到:

    你想要future的功能吧

    【 在 origin008 的大作中提到: 】

    ☆─────────────────────────────────────☆

     flybb (倒影) 于  (Thu May 11 07:59:58 2017)  提到:

    c++标委会是学院派的,不在乎你用的爽不爽

    c# java qt都有函数判断线程是不是已经结束

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     hxd32 (ben) 于  (Thu May 11 08:04:50 2017)  提到:

    lz不像是个程序员,那个版友解释得很清楚。判断线程任务完成和回收线程是两码事,先判断任务是否完成,然后主线程再回收子线程。

    【 在 origin008 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Thu May 11 10:42:26 2017)  提到:

    我是个干活的

    不是教书的

    请告诉我用现有的std库,怎么优雅地判断线程任务是否完成?

    至于回收子线程,这是程序猿该管的事情吗?

    【 在 hxd32 @ [CPlusPlus] 的大作中提到: 】

    ☆─────────────────────────────────────☆

     vonNeumann (劣币驱逐良币 | 少灌水) 于  (Thu May 11 10:49:59 2017)  提到:

    不要求优雅的话,有很多种方法可以干,用平台相关的代码,自己搞个 flag 什么的都行

    如果说要优雅…… 就算给你一个可以判断完成的函数,你确定你的忙等方案就很优雅?

    前面有人说了 future 你不知道是什么又不愿意去学,那怪谁咯

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     hgoldfish (老鱼) 于  (Thu May 11 11:05:00 2017)  提到:

    如果你不想管线程,只关心任务是否完成,最简单的办法确实就是放个标志量,或者使用管道来通信。

    但,对于干活,不论是自己放标志量,还是使用线程,都太低级了。高级点就是使用 future 和 std::async(),我觉得离线程还不远,不够抽象。。

    这时候我就不得不出来鼓吹一下 Qt 了。在 QtConcurrent 里面有很多更好用的:

    blockingmapped()

    blockingmappedReduced()

    mapped()

    filtered()

    reduced()

    run()

    优雅??什么叫优雅??这就是!

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     jimmycmh (Jimmy) 于  (Thu May 11 11:29:35 2017)  提到:

    join的功能是回收线程的返回值,不是用来判断线程是否结束的

    实现这个功能可以用个共享变量

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     jimmycmh (Jimmy) 于  (Thu May 11 11:33:08 2017)  提到:

    Go语言信号机制也设计得很不错

    【 在 hgoldfish (老鱼) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     speedboy2998 (极品飞车) 于  (Thu May 11 12:14:32 2017)  提到:

    用类的成员函数做线程函数,然后设置一个成员变量 mThreadShutdownState;

    在线程函数里:

    void myWorks::threadProc()

    {

    while (!mThreadShutdownState)

    {

    // do something

    }

    }

    bool myWorks::isThreadShutdown()

    {

    return mThreadShutdownState;

    }

    void myWorks::shutdownThread()

    {

    mThreadShutdownState = false;

    }

    【 在 origin008 的大作中提到: 】

    ☆─────────────────────────────────────☆

     ziqin (子青|会挽雕弓如满月|西北望|射天狼) 于  (Thu May 11 12:56:08 2017)  提到:

    伸手党都是〇〇被惯出来的

    连审美都没有,谈什么优雅

    【 在 hgoldfish (老鱼) 的大作中提到: 】

    用管道来通信。

    future 和 std::async(),我觉得离线程还不远,不够抽象。。

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Thu May 11 12:58:43 2017)  提到:

    你要知道C#和Java的线程都是Managed线程……

    【 在 flybb (倒影) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Thu May 11 13:00:32 2017)  提到:

    淡定,不要粗口,我修改一下你的帖子

    【 在 ziqin (子青|会挽雕弓如满月|西北望|射天狼) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     ysheshang (<map and target>) 于  (Thu May 11 13:11:55 2017)  提到:

    修改之后,看不出来原意了

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     ysheshang (<map and target>) 于  (Thu May 11 13:39:48 2017)  提到:

    joinable还是有作用的,如果join两次的话,抛出系统异常

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Thu May 11 14:26:00 2017)  提到:

    你们全家都很审美!

    【 在 ziqin 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Thu May 11 17:04:26 2017)  提到:

    伸手党新高度

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Thu May 11 17:22:52 2017)  提到:

    我伸什么手了?

    我让你们写代码了吗?

    你们这帮家伙,都是程序设计艺术系的叫兽吗?!

    【 在 sunseraphic @ [CPlusPlus] 的大作中提到: 】

    ☆─────────────────────────────────────☆

     ann77 (ann) 于  (Thu May 11 18:04:49 2017)  提到:

    http://stackoverflow.com/questions/9094422/how-to-check-if-a-stdthread-is-still-running

    http://en.cppreference.com/w/cpp/thread/thread/joinable

    这两个连接我帮你 google 搜索到的。加油啊!

    其他人的语气的确不是很友好。

    【 在 origin008 的大作中提到: 】

    ☆─────────────────────────────────────☆

     namelij (namelij) 于  (Thu May 11 18:38:28 2017)  提到:

    re,这个满足

    【 在 poikilotherm 的大作中提到: 】

    ☆─────────────────────────────────────☆

     OSN10 (老洪) 于  (Thu May 11 19:11:05 2017)  提到:

    同赞qt,好用不装

    【 在 hgoldfish (老鱼) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     OSN10 (老洪) 于  (Thu May 11 19:12:52 2017)  提到:

    我支持你,问个问题也被人讲粗口,这就是回答者的素质问题了

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Thu May 11 19:29:17 2017)  提到:

    粗口倒无所谓

    问题在于你问她为什么磁铁吸不起来不锈钢杯子,她教你去好好看看全套的理论物理教程!不看就是伸手党!

    【 在 OSN10 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Thu May 11 19:31:22 2017)  提到:

    其实我也Google过

    前面其它坛友也提到过

    我只是好奇std::thread的设计者提供joinable函数而不提供判断线程是否运行结束的函数,是出于一种什么样的考虑

    【 在 ann77 的大作中提到: 】

    ☆─────────────────────────────────────☆

     OSN10 (老洪) 于  (Thu May 11 19:35:06 2017)  提到:

    要说他讲的内容有道理,你这个问题看似技术问题,其实反应了你没把

    问题想清楚

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Thu May 11 19:38:43 2017)  提到:

    我只是个线程类的用户

    不是程序设计艺术工作者

    我的问题很简单,不要想得那么复杂

    就算不得不负责,也得简单地说明为什么要这么复杂

    另外,不直接回答一个问题,而说提问者没有把问题想清楚,是在是很艺术啊!

    【 在 OSN10 的大作中提到: 】

    ☆─────────────────────────────────────☆

     chusi (敛) 于  (Thu May 11 19:41:01 2017)  提到:

    弄个变量,线程最后一行代码改下那个变量不就完了

    【 在 origin008 的大作中提到: 】

    ☆─────────────────────────────────────☆

     OSN10 (老洪) 于  (Thu May 11 19:42:56 2017)  提到:

    他说明了啊,任务逻辑和线程接口要分开,这样看似不“友好”

    实际上避免了软件设计的许多日后难以解决的问题,不是挺清楚的吗

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Thu May 11 19:44:20 2017)  提到:

    这个变量得是全局的吧?

    或者另外弄个类把标准线程类再包装一下?

    标准线程类为什么不考虑弄个这种变量和接口呢?

    【 在 chusi 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Thu May 11 19:47:22 2017)  提到:

    道可道非常道

    说得清楚吗?

    【 在 OSN10 的大作中提到: 】

    ☆─────────────────────────────────────☆

     OSN10 (老洪) 于  (Thu May 11 19:49:13 2017)  提到:

    这个...我感觉你作为学生不太虚心也不太努力啊,他说你伸手党

    也不是没道理...

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     chusi (敛) 于  (Thu May 11 20:18:59 2017)  提到:

    我也不知道,十来年没用c++了

    【 在 origin008 的大作中提到: 】

    ☆─────────────────────────────────────☆

     ann77 (ann) 于  (Thu May 11 20:49:53 2017)  提到:

    本身判断一个线程是否结束是一个少见的需求。

    原因就是其他网友说的,要区分任务和线程是两个不同的概念。我就不重复了。深究原因,是一个很大的话题,如何设计程序的设计模式。

    关于c++11 标准为啥定义成现在这样,可以搜索n2345.PDF 之类的ISO 标准技术建议稿,标准委员会的工作组讨论记录在案

    【 在 origin008 的大作中提到: 】

    ☆─────────────────────────────────────☆

     ziqin (子青|会挽雕弓如满月|西北望|射天狼) 于  (Thu May 11 21:40:51 2017)  提到:

    不用和做一辈子码奴的人浪费时间。

    连最小设计准则都不接受的人,别说构架了,估计独立

    让他写个类都不行。

    less is more, simlpe is beauty

    【 在 OSN10 (老洪) 的大作中提到: 】

    他说你伸手党

    ☆─────────────────────────────────────☆

     blitz (blitz) 于  (Thu May 11 21:52:25 2017)  提到:

    讨论技术怎么就把大帽子给扣上了呢,还用上码奴这种侮辱性的称呼。

    【 在 ziqin (子青|会挽雕弓如满月|西北望|射天狼) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     xiaoxuanxuan (xiaoxuanxuan) 于  (Thu May 11 22:50:00 2017)  提到:

    我个人也觉得那个版友解释的很透彻,joinable是给系统回收资源用的,说的不是很清楚吗,c#那些所谓的优雅也是底层有相应的实现的,说白了趋向于傻瓜式编程呗,c++这种本来相比较就是开放了更多底层的功能给程序员,如果你觉得没用或者不认同,那么最好转到java或者c#呗

    【 在 origin008 () 的大作中提到: 】

    ☆─────────────────────────────────────☆

     here080 (hero080) 于  (Fri May 12 02:39:10 2017)  提到:

    楼主不要听楼上的人乱喷。

    你的要求非常合理。

    std::thread之所以不直接支持,是因为支持这个功能会带来额外的开销。而c++一向的设计原则是极端效率优先。

    实际上,好的多线程程序很多时候是需要使用这个判断的。

    更一般性的,你的需求是一个select()

    select({thread1.OnJoinable(), thread2.OnJoinable(), ...});

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     here080 (hero080) 于  (Fri May 12 02:44:09 2017)  提到:

    如果是java,这样搞很容易。可是c++里变量还有所有权的问题。

    只能写个MyThread包一层了。

    【 在 chusi (敛) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     ziqin (子青|会挽雕弓如满月|西北望|射天狼) 于  (Fri May 12 10:21:59 2017)  提到:

    这帮java程序员在说什么?

    【 在 here080 的大作中提到: 】

    ☆─────────────────────────────────────☆

     ziqin (子青|会挽雕弓如满月|西北望|射天狼) 于  (Fri May 12 10:29:59 2017)  提到:

    你确定你不是在说qt嘛?qt的变量所有权是signal机制造成的,怎么变成c++的特性了

    【 在 here080 的大作中提到: 】

    ☆─────────────────────────────────────☆

     lushan5436 (密如) 于  (Thu May 18 10:04:36 2017)  提到:

    他其实,说明了,为什么没有,因为C++中的线程是底层对象直接与操作系统内核对象关联,而不是像其他语言封装了一层。

    而你说的线程执行过程,里面的结束,显然与操作系统内核里管理线程的结束不是一回事。

    执行方法完成,是应用程序上层逻辑。

    【 在 origin008 的大作中提到: 】

    【 在 origin008 (Origin) 的大作中提到: 】

    : 本来以为joinable可以判断

    : 但仔细看了看说明,发现其实不行,这个函数其实没有存在的必要。

    : 我记得一个已经开始的进程,如果不被deatch,不被join,那么它在结束之前都是joinable的

    : 【 在 origin008 (Origin) 的大作中提到: 】

    : : 本来以为joinable可以判断

    : : 但仔细看了看说明,发现其实不行,这个函数其实没有存在的必要。

    : 问题是在结束之后、join之前,它也是joinable的!

    : 问题是在结束之后、join之前,它也是joinable的!

    : 那就join一下被,如果结束了,join就立马返回了啊

    : 【 在 origin008 (Origin) 的大作中提到: 】

    : : 问题是在结束之后、join之前,它也是joinable的!

    : 【 在 origin008 的大作中提到: 】

    : : 问题是在结束之后、join之前,它也是joinable的!

    : :

    : join是阻塞的啊

    : 我的目标是这样:

    : 主线程:

    : ...................

    : 你这是在启动的工作线程判断工作是否完成?

    : 是啊

    : 主线程启动工作线程,然后循环接收用户命令、判断是否结束工作线程。如果工作线程自己结束,就主程序也退出。

    : 这应该是比较典型的模式吧?

    : ...................

    : 是啊

    : 主线程启动工作线程,然后循环接收用户命令、判断是否结束工作线程。如果工作线程自己结束,就主程序也退出。

    : 这应该是比较典型的模式吧?

    : ...................

    : 是啊

    : 主线程启动工作线程,然后循环接收用户命令、判断是否结束工作线程。如果工作线程自己结束,就主程序也退出。

    : 这应该是比较典型的模式吧?

    : ...................

    : join是阻塞的啊

    : 我的目标是这样:

    : 主线程:

    : ...................

    : 线程的任务是否完成和线程是否joinable是两个逻辑

    : 层面的东西。

    : 线程是否joinable是更底层的逻辑,在这层逻辑是系

    : 你启动工作线程后,join工作线程,任务完成了线程自己就会退出。看你的说法,你判断线程是否结束,也不做别的事情啊,不明白你这个设计的目的是什么?

    : 【 在 origin008 的大作中提到: 】

    : : 是啊

    : 线程的任务是否完成和线程是否joinable是两个逻辑

    : 层面的东西。

    : 线程是否joinable是更底层的逻辑,在这层逻辑是系

    : 除了逻辑学教材外,还有两个问题要请教:

    : 1、joinable函数对于thread类的使用者而言,有什么作用?thread类的设计者为什么要对用户开放这个函数?

    : 2、thread类的设计者提供一个低层次的joinable函数,而不提供一个更高层次的判断线程是否运行结束的判断函数,是出于什么考虑呢?

    : ...................

    : 最简单的例子,

    : 启动工作线程后等待接收用户的输入,

    : 用户如果命令退出,就提前结束返回

    : ...................

    : 你这不就是想根据用户指令终止工作线程吗? 最简单的办法设置一个flag,在工作线程判断flag退出线程不就得了?

    : 这个简单的一个功能,你喷人家thread至于么?

    : 【 在 origin008 的大作中提到: 】

    : : 最简单的例子,

    : 为什么不能喷呢?

    : 我觉得这个判断线程函数是否运行完毕的功能经常会用到,thread类设计者为什么不提供呢?

    : 提供的那个joinable函数,对thread类的用户而言又有什么作用呢?

    : 高层次的是: thread.isRunning 吧。 QThread 有。顺着这个思路搜了一下:

    https://codedump.io/share/tj0sUKbrspev/1/how-to-check-if-a-stdthread-is-still-running

    : 1 用 auto future = std::async(work_fun); auto status = future.wait_for(...); // status == ready 意味着已经结束

    : ...................

    : 你有没有想过,假如给你提供这个接口,你要怎么用?如果你判断到线程还在运行,你接下来怎么办?循环去判断直到运行结束?

    : 很简单啊,比如:

    : void foo(bool* p)

    : {

    : ...................

    : 你的peek_input()在用户没有输入的时候不会阻塞main thread?

    : 因为他是PEEK,所以不阻塞

    : :

    : 标  题: std::thread竟然不自带判断线程是否结束的功能?

    : 发信站: 水木社区 (Mon May  8 11:34:42 2017), 站内

    : 本来以为joinable可以判断

    : 但仔细看了看说明,发现其实不行,这个函数其实没有存在的必要。

    : --

    : 高层次的是: thread.isRunning 吧。 QThread 有。顺着这个思路搜了一下:

    https://codedump.io/share/tj0sUKbrspev/1/how-to-check-if-a-stdthread-is-still-running

    : 1 用 auto future = std::async(work_fun); auto status = future.wait_for(...); // status == ready 意味着已经结束

    : ...................

    : 这个可能是楼主需要的

    : c11的thread用的时候确实和之前不大一样,人家的理念就是让你面向任务,底层的事情交给他们吧

    : async让我不爽的是,如果我的任务就是没有返回呢

    : ...................

    : 除了逻辑学教材外,还有两个问题要请教:

    : 1、joinable函数对于thread类的使用者而言,

    : 2、thread类的设计者提供一个低层次的

    : ...................

    : 高层次的是: thread.isRunning 吧。 QThread 有。顺着这个思路搜了一下:

    https://codedump.io/share/tj0sUKbrspev/1/how-to-check-if-a-stdthread-is-still-running

    : 1 用 auto future = std::async(work_fun); auto status = future.wait_for(...); // status == ready 意味着已经结束

    : ...................

    : 还是做伸手党 我前面一个帖子已经把你需要去思考的

    : 东西说得很清楚了。

    : 你在本质上没有区分thread和task两个东西,这两个

    : 您训斥得很对,

    : 但我却听不懂。

    : 听得懂的版友请举手!

    : ...................

    :  您训斥得很对,

    :  但我却听不懂。

    :  听得懂的版友请举手!

    : 本来以为joinable可以判断

    : 但仔细看了看说明,发现其实不行,这个函数其实没有存在的必要。

    : 本来以为joinable可以判断

    : 但仔细看了看说明,发现其实不行,这个函数其实没有存在的必要。

    : 您训斥得很对,

    : 但我却听不懂。

    : 听得懂的版友请举手!

    : ...................

    : lz不像是个程序员,那个版友解释得很清楚。判断线程任务完成和回收线程是两码事,先判断任务是否完成,然后主线程再回收子线程。

    : 【 在 origin008 的大作中提到: 】

    : : 您训斥得很对,

    : : 但我却听不懂。

    : 标  题: Re: std::thread竟然不自带判断线程是否结束的功能?

    : 发信站: 水木社区 (Thu May 11 10:42:26 2017), 站内

    : 我是个干活的

    : 不是教书的

    : 请告诉我用现有的std库,怎么优雅地判断线程任务是否完成?

    : 至于回收子线程,这是程序猿该管的事情吗?

    : 【 在 hxd32 @ [CPlusPlus] 的大作中提到: 】

    : :

    : : lz不像是个程序员,那个版友解释得很清楚。判断线程任务完成和回收线程是两码事,先判断任务是否完成,然后主线程再回收子线程。

    : : 【 在 origin008 的大作中提到: 】

    : : : 您训斥得很对,

    : : : 但我却听不懂。

    : --

    : 我是个干活的

    : 不是教书的

    : 请告诉我用现有的std库,怎么优雅地判断线程任务是否完成?

    : ...................

    : 最简单的例子,

    : 启动工作线程后等待接收用户的输入,

    : 用户如果命令退出,就提前结束返回

    : ...................

    : 如果你不想管线程,只关心任务是否完成,最简单的办法确实就是放个标志量,或者使用管道来通信。

    : 但,对于干活,不论是自己放标志量,还是使用线程,都太低级了。高级点就是使用 future 和 std::async(),我觉得离线程还不远,不够抽象。。

    : 这时候我就不得不出来鼓吹一下 Qt 了。在 QtConcurrent 里面有很多更好用的:

    : ...................

    : 是啊

    : 主线程启动工作线程,然后循环接收用户命令、判断是否结束工作线程。如果工作线程自己结束,就主程序也退出。

    : 这应该是比较典型的模式吧?

    : ...................

    : 如果你不想管线程,只关心任务是否完成,最简单的办法确实就是放个标志量,或者使

    : 但,对于干活,不论是自己放标志量,还是使用线程,都太低级了。高级点就是使用

    : 这时候我就不得不出来鼓吹一下 Qt 了。在 QtConcurrent 里面有很多更好用的:

    : ...................

    : c++标委会是学院派的,不在乎你用的爽不爽

    : c# java qt都有函数判断线程是不是已经结束

    : 伸手党都是鸡巴被惯出来的

    : 连审美都没有,谈什么优雅

    : 用管道来通信。

    : ...................

    : 淡定,不要粗口,我修改一下你的帖子

    : 为什么不能喷呢?

    : 我觉得这个判断线程函数是否运行完毕的功能经常会用到,thread类设计者为什么不提供呢?

    : 提供的那个joinable函数,对thread类的用户而言又有什么作用呢?

    : 伸手党都是〇〇被惯出来的

    : 连审美都没有,谈什么优雅

    : 用管道来通信。

    : ...................

    : 你们全家都很审美!

    : 伸手党新高度

    : 【 在 origin008 (Origin) 的大作中提到: 】

    : : 你们全家都很审美!

    : 我伸什么手了?

    : 我让你们写代码了吗?

    : 你们这帮家伙,都是程序设计艺术系的叫兽吗?!

    : ...................

    :future/promise

    :【 在 origin008 的大作中提到: 】

    :...................

    : 如果你不想管线程,只关心任务是否完成,最简单的办法确实就是放个标志量,或者使用管道来通信。

    : 但,对于干活,不论是自己放标志量,还是使用线程,都太低级了。高级点就是使用 future 和 std::async(),我觉得离线程还不远,不够抽象。。

    : 这时候我就不得不出来鼓吹一下 Qt 了。在 QtConcurrent 里面有很多更好用的:

    : ...................

    : 我伸什么手了?

    : 我让你们写代码了吗?

    : 你们这帮家伙,都是程序设计艺术系的叫兽吗?!

    : ...................

    : 我支持你,问个问题也被人讲粗口,这就是回答者的素质问题了

    http://stackoverflow.com/questions/9094422/how-to-check-if-a-stdthread-is-still-running

    http://en.cppreference.com/w/cpp/thread/thread/joinable

    : 这两个连接我帮你 google 搜索到的。加油啊!

    : ...................

    : 粗口倒无所谓

    : 问题在于你问她为什么磁铁吸不起来不锈钢杯子,她教你去好好看看全套的理论物理教程!不看就是伸手党!

    : 要说他讲的内容有道理,你这个问题看似技术问题,其实反应了你没把

    : 问题想清楚

    : 本来以为joinable可以判断

    : 但仔细看了看说明,发现其实不行,这个函数其实没有存在的必要。

    : 标  题: Re: std::thread竟然不自带判断线程是否结束的功能?

    : 发信站: 水木社区 (Thu May 11 19:38:43 2017), 站内

    : 我只是个线程类的用户

    : 不是程序设计艺术工作者

    : 我的问题很简单,不要想得那么复杂

    : 就算不得不负责,也得简单地说明为什么要这么复杂

    : 另外,不直接回答一个问题,而说提问者没有把问题想清楚,是在是很艺术啊!

    : 【 在 OSN10 的大作中提到: 】

    : : 要说他讲的内容有道理,你这个问题看似技术问题,其实反应了你没把

    : : 问题想清楚

    : :

    : --

    : 弄个变量,线程最后一行代码改下那个变量不就完了

    : 他说明了啊,任务逻辑和线程接口要分开,这样看似不“友好”

    : 实际上避免了软件设计的许多日后难以解决的问题,不是挺清楚的吗

    : 标  题: Re: std::thread竟然不自带判断线程是否结束的功能?

    : 发信站: 水木社区 (Thu May 11 19:47:22 2017), 站内

    : 道可道非常道

    : 说得清楚吗?

    : 【 在 OSN10 的大作中提到: 】

    : : 他说明了啊,任务逻辑和线程接口要分开,这样看似不“友好”

    : : 实际上避免了软件设计的许多日后难以解决的问题,不是挺清楚的吗

    : :

    : --

    : 这个变量得是全局的吧?

    : 或者另外弄个类把标准线程类再包装一下?

    : 标准线程类为什么不考虑弄个这种变量和接口呢?

    : 其实我也Google过

    : 前面其它坛友也提到过

    : 我只是好奇std::thread的设计者提供joinable函数而不提供判断线程是否运行结束的函数,是出于一种什么样的考虑

    : ....................

    : 这个...我感觉你作为学生不太虚心也不太努力啊,

    : 也不是没道理...

    : 不用和做一辈子码奴的人浪费时间。

    : 连最小设计准则都不接受的人,别说构架了,估计独立

    : 让他写个类都不行。

    : ...................

    : 我是个干活的

    : 不是教书的

    : 请告诉我用现有的std库,怎么优雅地判断线程任务是否完成?

    : 至于回收子线程,这是程序猿该管的事情吗?

    : 标  题: std::thread竟然不自带判断线程是否结束的功能?

    : 发信站: 水木社区 (Mon May  8 11:34:42 2017), 站内

    : 本来以为joinable可以判断

    : 但仔细看了看说明,发现其实不行,这个函数其实没有存在的必要。

    : --

    : 标  题: Re: std::thread竟然不自带判断线程是否结束的功能?

    : 发信站: 水木社区 (Thu May 11 19:41:01 2017), 站内

    : 弄个变量,线程最后一行代码改下那个变量不就完了

    : 【 在 origin008 的大作中提到: 】

    : : 本来以为joinable可以判断

    : : 但仔细看了看说明,发现其实不行,这个函数其实没有存在的必要。

    : --

    : 如果是java,这样搞很容易。可是c++里变量还有所有权的问题。

    : 只能写个MyThread包一层了。

    : 如果是java,这样搞很容易。可是c++里变量还有所有权的问题。

    : 只能写个MyThread包一层了。

    : 道可道非常道

    : 说得清楚吗?

    : :

    2017-05-19
  • Re: 想建个小局域网,该用哪种方案?

    【 在 easior (lars) 的大作中提到: 】

    : 是指普通路由器+普通头网线?

    2017-05-18
  • Re: 想建个小局域网,该用哪种方案?

    3

    【 在 easior (lars) 的大作中提到: 】

    : 三台以上电脑,建星形局域网实现两两互联:

    : 1、用一台电脑作网关。这个方法经常看到,但想不通网关怎么连两台以上的电脑?

    : 2、集线器。不知道有没有 ip 地址分配功能?

    : ...................

    2017-05-18
  • Re:请问精通python的同学, 都在做什么工作啊

    这个问题已经发了好几遍了

    【 在 wint 的大作中提到: 】

    :这个好像是个机器人。每个版发一个类似的问题。

    :【 在 dUIya 的大作中提到: 】

    :: 谢谢

    :...................

    2017-05-14
  • [合集] 在C/C++语言中,检测指针是否为NULL有意义吗?

    ☆─────────────────────────────────────☆

     wxsoar (嘿嘿) 于  (Sat Mar 15 01:41:36 2014)  提到:

    今天和测试人员发生强烈争论,是关于指针的

    我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应该由调用者进行保证,而不应该将问题提给函数的实现者

    不知各位大牛有何高见呢?

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Sat Mar 15 01:43:18 2014)  提到:

    他们希望你门检测到空指针以后做什么呢?抛一个NullPointerException吗?

    ☆─────────────────────────────────────☆

     kobe2000 (意义) 于  (Sat Mar 15 07:29:24 2014)  提到:

    靠,和我经历一样

    【 在 wxsoar 的大作中提到: 】

    ☆─────────────────────────────────────☆

     aqhistory (江小坏) 于  (Sat Mar 15 08:21:48 2014)  提到:

    库作者宽入严处是基本素质。

    【 在 wxsoar 的大作中提到: 】

    ☆─────────────────────────────────────☆

     SelaSelah (斯啦丝拉) 于  (Sat Mar 15 08:27:23 2014)  提到:

    开源的程序一般都是将这个交由调用者来做的,很多代码甚至没有输入检查,这是因为开源的东西一般都是大牛在整。

    而公司的商业开发最好要做输入检查,员工参差不齐,大家重视的是KPI什么的,不能保证每个程序员都有很高的水准,或者对他要调用的东西有深入的理解。

    【 在 wxsoar 的大作中提到: 】

    ☆─────────────────────────────────────☆

     wxsoar (嘿嘿) 于  (Sat Mar 15 08:40:22 2014)  提到:

    检查了,代码不会很ugly吗,难道还要继续判断不为-1,-2……吗,那代码该怎样写?

    【 在 SelaSelah 的大作中提到: 】

    ☆─────────────────────────────────────☆

     bluehearts (Don't wanna miss a thing) 于  (Sat Mar 15 08:41:03 2014)  提到:

    这个有需求文档没有? 你们提供了API的文档没有.

    NULL指针是什么行为按照需求和API的文档来呀.

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序

    自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起

    去!

    ☆─────────────────────────────────────☆

     SelaSelah (斯啦丝拉) 于  (Sat Mar 15 08:45:05 2014)  提到:

    恩,我也觉得十分SB

    给个指针变量那SB非要传个非法值进来,那不是找贱么,不过总是有这样的人。

    我觉得检测下== 0/NULL 就好,可以应付大部分出错了。一般也就是调用方疏忽了,或者上一次函数调用让指针变为NULL了。

    如果是野指针什么的无能为力。

    还有C++不是有个nullptr了么。

    【 在 wxsoar 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Goldhead (我不知道) 于  (Sat Mar 15 09:39:37 2014)  提到:

    支持不检测,除非0是一个有约定的特殊输入

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     jjfz (每天两壶茶) 于  (Sat Mar 15 10:03:02 2014)  提到:

    不需要检测,就直接拿strcmp之类的函数作为例子

    除非它们另有要求,否则即使检测到了能干嘛?抛异常么

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     PGP (---) 于  (Sat Mar 15 10:05:12 2014)  提到:

    你写清楚传入非法值会crash on purpose就好了

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     fanci (大葡萄) 于  (Sat Mar 15 10:23:41 2014)  提到:

    贵司的测试人员太奇葩。

    测试Null主要功能是帮助调试,对于生产系统没啥意义。

    【 在 wxsoar () 的大作中提到: 】

    ☆─────────────────────────────────────☆

     alanju (alanju) 于  (Sat Mar 15 11:17:34 2014)  提到:

    修改一下:按照约定来做。约定调用者来检查就调用者检查。

    ==================================

    如果ptr可能是NULL,应该代码要处理。

    如果ptr不可能是NULL, 建议用断言。

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测

    试,

    测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么

    都说不到一起去!

    ☆─────────────────────────────────────☆

     wxsoar (嘿嘿) 于  (Sat Mar 15 11:30:51 2014)  提到:

    我觉得你这个观点很有道理,将指针设为0,一般有两种考虑,

    一是调用者和被调用者将其作为特殊值约定,

    二是开发组织对指针定义具有约定,要求所有指针定义都必须初始化为0,

    这两种情况都有个前提,就是必须提前对0的使用有个要求

    而我们并没有这个要求,这种情况下,

    0值其实和其它非法指针并无差别

    如果有问题,也是编程风格的问题,而不应该是严重问题

    【 在 Goldhead 的大作中到: 】

    ☆─────────────────────────────────────☆

     kirbyzhou (下雪 你那边下雪了么?) 于  (Sat Mar 15 11:32:42 2014)  提到:

    assert就好了

    【 在 alanju (alanju) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     wxsoar (嘿嘿) 于  (Sat Mar 15 11:35:30 2014)  提到:

    这是个好主意,可是开始并没有写啊,现在去加他们又不干

    另,在c语言中,使用非法指针,

    结果无法预期,难道不是语言自身的规则吗

    【 在 PGP 的大作中提到: 】

    ☆─────────────────────────────────────☆

     liuxueshen ( rock) 于  (Sat Mar 15 11:46:00 2014)  提到:

    没有文档说明,请老大搞定,这已经超出你的能力范围了;

    老大搞不定,继续找上层,这不属于技术范畴了,属于代码分工。

    语言自身规则要保证多数应用情况,

    如果你写的这个库也向stdlib一样的应用范围,可以直接无视测试人员,

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     wxsoar (嘿嘿) 于  (Sat Mar 15 11:56:58 2014)  提到:

    求解释

    ---------------------------

    【 在 liuxueshen 的大作中提到: 】

    ☆─────────────────────────────────────☆

     piggestbaby (吃的胖胖的(~~**~~)) 于  (Sat Mar 15 14:40:42 2014)  提到:

    你这种情况, 有些意义

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     thinelephant (象瘦毛长) 于  (Sat Mar 15 15:26:00 2014)  提到:

    我一直非常同意你的观点。

    程序执行是需要遵守规定的。我规定了输入指针指向啥,你就该给我传啥。规定可以写在 API 文档里面,如果文档没写明白,那是我的问题。但是看看一般 Linux 下面的 man 手册,如果不说,默认就是不能传 NULL,如果约定 NULL 表示某种特殊含义,肯定会在文档里面写出来的。

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     liuxueshen ( rock) 于  (Sat Mar 15 15:33:21 2014)  提到:

    你做到库如果应用只在公司级别的,那么在进行架构设计的时候就应该

    确定下来的,之后各个模块才能确定工作量;

    现在的实际情况显然是当时没有做这么详细,那自然再回到架构师那里让他来确定;

    确定后重新核定工作量。

    你说的那些理由都是大家编程习惯,在公司里面都是可以改变的;

    但是工作量直接挂钩工资的,没有明确的情况下,你不能以IT默认的编程习惯要求

    别人增加工作量。

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     perfectfan (Nicky) 于  (Sat Mar 15 15:37:31 2014)  提到:

    我也认同你。调用你函数的又不是没有编程经验的终端客户。搞的跟那些手工测试一样。

    【 在 wxsoar 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Soloman (等发了财,我就去参悟佛经) 于  (Sat Mar 15 18:23:04 2014)  提到:

    我觉得大部分码农写代码的时候,也不是在调用函数前,先检查一下调用参数是否非法,而是在函数里面,检查参数范围。写库难道不是这样?

    【 在 SelaSelah (斯啦丝拉) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     xshoushoux (xshoushoux) 于  (Sat Mar 15 18:24:56 2014)  提到:

    问题是指针是否非法根本没法查,不如直接core dump

    【 在 Soloman (等发了财,我就去参悟佛经) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     kobe2000 (意义) 于  (Sat Mar 15 21:08:35 2014)  提到:

    有办法检查指针合法?

    【 在 Soloman 的大作中提到: 】

    ☆─────────────────────────────────────☆

     roamer2889 (F458) 于  (Sat Mar 15 21:56:34 2014)  提到:

    很多时候不是讲道理就能行得通的。

    假设如下一个情况:你们公司是卖库的,库的潜在用户有高手有菜鸟,是菜鸟用户试用你们的库的时候不小心传递了一个null给api函数因为你没有检查程序崩了,你就有可能失去了这个客户,他不认为是自己的错,可能认为是你们的库不够稳定不够安全。 如果你检查了null指针,并返回一个特定的值,比如自己定义的枚举类型:eptrnull,这个菜鸟看了返回值就明白了。

    不要把用户想得和你一样牛,你要把用户想成白痴,

    【 在 wxsoar 的大作中提到: 】

    ☆─────────────────────────────────────☆

     kobe2000 (意义) 于  (Sat Mar 15 23:05:06 2014)  提到:

    很有意思的一个现象:cpp版和c版对这个问题的态度迥异。和cpp和c的语言特性一致

    ☆─────────────────────────────────────☆

     vonNeumann (劣币驱逐良币) 于  (Sat Mar 15 23:22:04 2014)  提到:

    对外的接口吗?对外的接口我还是主张要严格检查参数,调用者不一定熟悉你的系统,人和人之间的沟通不一定那么有效那么准确。检查得严格,出了问题也好推责任……

    另外 NULL 对硬件来说是一个普通的非法指针,对软件开发者来可说不是,它被赋予了特殊含义。

    要是项目内部的接口,看情况吧。一个文件内的 static 函数,那就不检查了。

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     wz911 (晃来晃去) 于  (Sat Mar 15 23:24:14 2014)  提到:

    【 在 wxsoar 的大作中提到: 】

    当然有必要,给你说个真实的例子,某设备商的设备,开发人员在调用平台接口的时候参数多写了个*导致指针引用错误,0指针导致cpu复位,不幸的是测试没有覆盖到,最后发给运营商,更不幸的是准入测试也没有覆盖到,然后业务切换,一切正常,某天,某个功能引发这个问题,导致整个设备重启,更不幸的事情发生了,这种状态的重启也触发这个问题,业务切换动作扩散,导致某个城市的某款设备的某个版本的软件不停复位,耗时几个小时,全部相关网络瘫痪,电话,宽带,手机,

    这种后果你想过么???

    现在再回答一下这个问题,指针为0需要检查么?

    ☆─────────────────────────────────────☆

     xshoushoux (xshoushoux) 于  (Sat Mar 15 23:52:31 2014)  提到:

    真把用户想成白痴的话,你觉得他会好好检查你函数的返回值吗?

    静悄悄地返回一个错误码,还不如core dump来得好

    【 在 roamer2889 (F458) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     javaboy (喝了咖啡就话多-_-;) 于  (Sun Mar 16 00:13:02 2014)  提到:

    检查NULL也不能解决这个问题。

    【 在 wz911 (晃来晃去) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     vonNeumann (劣币驱逐良币) 于  (Sun Mar 16 00:17:28 2014)  提到:

    别全从技术角度来考虑了,有时候从个人的角度考虑下。如果级别还不够为整个系统操心的时候,那就先别操那么大的心,先把自己该操心的部分管好

    想想如果生产环境出了事故,要追究责任的时候…… 你返回了错误码,他没检查,那没有疑问他要负所有责任。如果他传了一个野指针进来,在你的代码里崩了,也是他全责。但如果传了一个 NULL,而文档里万一又不清楚的话,那不好意思,你可能得被迫承担一部分责任

    【 在 xshoushoux (xshoushoux) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Antonioni (越薄越尽兴) 于  (Sun Mar 16 00:24:14 2014)  提到:

    你要是爱吵架就接着吵 不爱吵架就找个爱吵架的接着吵 这东西没对错吧

    【 在 wxsoar 的大作中提到: 】

    ☆─────────────────────────────────────☆

     roamer2889 (F458) 于  (Sun Mar 16 00:35:10 2014)  提到:

    还是这个例子,如果不检查NULL,直接CORE DUMP,菜鸟检查代码,调试,发现是传递了NULL指针导致的,很多菜鸟直接会这么想:什么垃圾库,连空指针都不检查都导致崩溃。

    如果对于NULL返回一个错误代码,但是菜鸟没有检查这个错误代码,所以接下来继续操作调用别的API,因为上一个API调用已经失败,所以接下来的API也会失败,最后他的需要的功能不能正常工作, 他只好回头检查代码,检查返回值,看文档,最后发现是自己问题,那么他的印象和上一个完全是两回事:这个库挺不错的,函数直接返回了错误代码告诉我哪里出了问题。

    假设有两个公司卖的开发包分别是用以上两种方式来处理NULL指针,大多数菜鸟用户会选择购买哪个库?(假设其他功能都同等的情况下)

    【 在 xshoushoux 的大作中提到: 】

    ☆─────────────────────────────────────☆

     IDVolume (我喊!) 于  (Sun Mar 16 00:57:05 2014)  提到:

    大哥,程序的健壮性,最基本的一条要求就是跨模块要查参数的

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     IDVolume (我喊!) 于  (Sun Mar 16 01:01:13 2014)  提到:

    kao,这个问题还用需要讨论两页?水平下降了啊

    【 在 IDVolume (我喊!) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     xshoushoux (xshoushoux) 于  (Sun Mar 16 01:04:21 2014)  提到:

    你和楼上说的都有道理,跳出技术范畴看这个问题,答案确实很不一样

    (当然即使纯技术范畴,应该也存在宁愿bug被藏起来但只要晚暴露一天就好一天的系统

    ,还是不能一概而论)

    【 在 roamer2889 (F458) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     coocodelie ( 懒得输入) 于  (Sun Mar 16 03:08:09 2014)  提到:

    写程序没超过5年?

    要不然就是你周围都是大牛。

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测

    试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不

    到一起去!

    ☆─────────────────────────────────────☆

     PGP (---) 于  (Sun Mar 16 03:33:04 2014)  提到:

    标准库也不会检查的,也没看谁抱怨

    【 在 roamer2889 (F458) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     roamer2889 (F458) 于  (Sun Mar 16 09:39:53 2014)  提到:

    你确定你看懂了我说的什么?

    【 在 PGP 的大作中提到: 】

    ☆─────────────────────────────────────☆

     xbgg (小笨.思の刃) 于  (Sun Mar 16 10:04:29 2014)  提到:

    被人搞死的次数太少......

    一个项目, 十多人合作, 每个人水平不一定, 你敢这么写..... 你这样的系统要不经常崩溃才是怪事

    一个人自己写个全系统的可能没问题, 不过这不能说做过大系统.

    【 在 PGP (---) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     lester98 (奶瓶) 于  (Sun Mar 16 10:35:24 2014)  提到:

    在错误指针传进来的情况下,有很大概率是0指针,个人感觉超过一半,所以,如果做null检测就降低一半死机的情况,何乐而不为呢?

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Sun Mar 16 15:17:05 2014)  提到:

    支持在Debug模式 进行输入检查就行了

    我自己写自己用的 都这么干 防止低级错误

    【 在 roamer2889 的大作中提到: 】

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Sun Mar 16 15:20:17 2014)  提到:

    debug模式进行检测  一些开源的库 都有这样的 而不是碰到错误 直接崩溃

    【 在 roamer2889 的大作中提到: 】

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Sun Mar 16 15:24:43 2014)  提到:

    针对每一个函数写一个 入口检查函数

    matlab就这么搞得

    比如  void DoSomething(int a, int b)

    就写一个 bool CheckInput_DoSomething(int a, int b)

    void DoSomething(int a, int b)

    {

    #if defined DEBUG

    if (CheckInput_DoSomething(a, b))

    {

    做提示 还是直接崩溃

    }

    #endif

    【 在 wxsoar 的大作中提到: 】

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Sun Mar 16 15:27:25 2014)  提到:

    如果你写的这个库也向stdlib一样的应用范围,可以直接无视测试人员,

    stdlib 要讲究效率 不可能给你提供详细的输入检查

    【 在 liuxueshen 的大作中提到: 】

    ☆─────────────────────────────────────☆

     loser002 (做一个写程序最极品的屌丝) 于  (Sun Mar 16 16:30:17 2014)  提到:

    没看懂

    如果你设计的函数都认为null是非法的,那么用户传null,你的程序崩溃,不就是检查吗?测试人员还要怎么检查?我觉得debug模式下加assert足够了。

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     loser002 (做一个写程序最极品的屌丝) 于  (Sun Mar 16 16:31:56 2014)  提到:

    函数设计,基本要求就是 传入合法的能得到合法结果,传入非法的得到非法结果抛异常或者崩溃就行啊。

    最怕的是,传入合法或者非法的参数,你给人家一个ub的飘忽不定的结果。。

    【 在 SelaSelah (斯啦丝拉) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     milksea (肥了,又肥了 >>>_<<<) 于  (Sun Mar 16 16:34:09 2014)  提到:

    我觉得吧,加个 assert 就行了。

    理由:

    * 实现方好写,比其他方式判断省事。

    * 调试模式下(未定义 NDEBUG 宏)照样会死,不过死了后错误信息友好一些,也就是死得好看点。

    * 产品编译(定义了 NDEBUG 宏)等于没有,不影响任何效率之类的东西。

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     loser002 (做一个写程序最极品的屌丝) 于  (Sun Mar 16 16:34:28 2014)  提到:

    visual studio有没有编译选项 自动生成参数检查的代码?这样在release/debug下面都能保证传入非法null参数,程序立刻崩溃,就一句判断是否为null的代码,对函数性能影响不大吧

    【 在 BrightLiang (WenQiang Xu@米国) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     milksea (肥了,又肥了 >>>_<<<) 于  (Sun Mar 16 16:35:23 2014)  提到:

    编译器哪儿敢假定哪个指针参数允许 NULL 哪个又不允许的?

    【 在 loser002 (做一个写程序最极品的屌丝) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     loser002 (做一个写程序最极品的屌丝) 于  (Sun Mar 16 16:37:08 2014)  提到:

    我就随便问问。不过为什么不可以假定呢? 完全可以添加这个编译选项。我觉得楼主的意思他们的库都认为传入null是非法的,如果编译器提供这样的选项,直接对参数指针在debug下加assert,再release下直接嵌入句汇编判断。。那么,楼主只要打开这个编译开关编译出程序给测试,就没问题了

    【 在 milksea (肥了,又肥了 >>>_<<<) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     NIGHTFIRE (昵称不告诉你们) 于  (Sun Mar 16 17:51:19 2014)  提到:

    这种事为什么不用宏呢……

    自动化也是插桩工具比较自然吧?

    【 在 loser002 (做一个写程序最极品的屌丝) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     SelaSelah (斯啦丝拉) 于  (Sun Mar 16 19:31:20 2014)  提到:

    我只能认同一半。

    一个函数,传入合法的参数,一定要得到合法的结果。其实做到这步都很难,可移植性以及跨平台,还有线程安全,等等。

    至于另一半,我认为点到为止即可,事实上,我认为完全可靠的函数是没有的,即使你设计再多的输入检查。

    从标准库到各种用户库,符合我观点的不计其数,我可以摘录几个:

    stdc:

    memcpy - The  memcpy()  function  copies  n bytes from memory area src to memory

    area dest.  The memory areas must not overlap.  Use memmove(3)  if  the

    memory areas do overlap.

    我试验了下,如果内存区域重叠了,果然是UB,什么警告都没有

    fclose - In either case any further access (including another call to fclose()) to the stream results in undefined behavior.

    stdc++:

    std::for_each

    Throws if fn throws or if any of the operations on iterators throws.

    Note that invalid arguments cause undefined behavior.

    gcc没有for_each的文档,我摘得cplusplus的文档。

    我用的vector迭代,end放到begin前边,依旧毫无对应,打印了一大堆空白然后段错误了,估计是把整个栈给打印了一遍。

    我觉得,只要目的是作死,再健全的函数也能整成UB,不信可以写一个简单的我试一试。

    【 在 loser002 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Goldhead (我不知道) 于  (Sun Mar 16 19:43:13 2014)  提到:

    说个题外话,记得linus好像喷过glibc的memcpy实现,他说kernel里memcpy直接就是做

    成memmove的alias,然后说glibc也应该这么办

    导火线是glibc的memcpy某个版本的改动导致adobe flash出了问题(flash里有一个

    memcpy的调用参数是overlap的,adobe的码农。。。),linus就狂喷了一通,说memcpy就应该做成memmove的alias,blablabla

    【 在 SelaSelah (斯啦丝拉) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Sun Mar 16 19:53:29 2014)  提到:

    assert就是宏

    【 在 NIGHTFIRE (昵称不告诉你们) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     SelaSelah (斯啦丝拉) 于  (Sun Mar 16 19:54:13 2014)  提到:

    挺有意思,linus似乎是个隐藏的喷神,还喷过debug

    【 在 Goldhead 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Sun Mar 16 20:05:41 2014)  提到:

    msvc的memcpy一直都是memmov

    【 在 Goldhead (我不知道) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Goldhead (我不知道) 于  (Sun Mar 16 20:25:30 2014)  提到:

    一点儿都不隐藏,老喷了,用词也比较粗糙,什么bullshit、brain damaged张口就来

    当然也有比较文雅的时候,比如他是这么喷powerpc的:

    "The memory management on the PowerPC can be used to frighten small children."

    【 在 SelaSelah (斯啦丝拉) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     RaulBC (边疆芳草,亲亲一家人) 于  (Sun Mar 16 20:27:24 2014)  提到:

    不检查可以的,但是需要有annotation和assert.

    因为有些api是可以传空指针的。你必须在函数声明的时候,给调用者和code analysis工具声明好。

    wxsoar 的大作中提到: 】

    ☆─────────────────────────────────────☆

     NIGHTFIRE (昵称不告诉你们) 于  (Sun Mar 16 20:48:13 2014)  提到:

    第一句“为什么不用宏”就是针对的assert

    第二句“插桩工具”针对连assert都懒得写,想自动assert所有指针的po主

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Mon Mar 17 02:17:23 2014)  提到:

    和这里大多数支持不检查的观点不同,我的观点是,如果你的文档里没有注明不能是nullptr,那可以是nullptr,就要检查。

    我认为在没有文档的情况下,通常的约定是:

    1)引用输入:不能是nullptr,函数本身不用检查;

    2)指针输入:可以是nullptr,函数本身需要检查。

    像const char*这种,如果你想向调用者表明不能是nullptr,最好用const string&或者StringPiece之类的。如果是output buffer的char*,最好用string&之类的吧。

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    今天和测试人员发生强烈争论,是关于指针的

    我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应该由调用者进行保证,而不应该将问题提给函数的实现者

    不知各位大牛有何高见呢?

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Mon Mar 17 02:31:02 2014)  提到:

    没有

    【 在 loser002 的大作中提到: 】

    ☆─────────────────────────────────────☆

     wz911 (晃来晃去) 于  (Mon Mar 17 11:07:18 2014)  提到:

    【 在 javaboy 的大作中提到: 】

    在那个故障问题如果加了NULL检查,至少能保证不会全系统重启,业务倒换失败的问题虽然严重,但是还是可控,如果整个系统挂掉,如果你有去局方出差的经历,你就会知道后果有多严重,

    在软件设计过程中除了极少数模块对性能要求极其高的情况下,会对参数的检查做某些妥协,一般软件特别是平台软件都要求接口处对参数做相当的校验,比如指针是否为空,参数是否在克里范围内还有些设计要求在正式配置之前要有test配置过程,

    参数检查从来都不能解决所有问题,但是能有效减少致命问题的出现可能,你明知道空指针必然导致系统挂掉,还非说不能解决所有问题,不做任何检查,这点都意识都没有的话,你就别做软件了,压根就不是做软件的材料,也没有能力开发稍微大型一点的软件。

    ☆─────────────────────────────────────☆

     Goldhead (我不知道) 于  (Mon Mar 17 11:17:45 2014)  提到:

    太绝对了,不同domain情况不一样

    在你那儿也许尽最大可能让程序不崩是最高的优先级,但也有很多场景下让程序原地崩掉

    是更好的选择

    不检查NULL和性能要求无关,很多情况下是故意为之

    这和一般的检查输入参数合理范围不一样

    【 在 wz911 (晃来晃去) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     javaboy (喝了咖啡就话多-_-;) 于  (Mon Mar 17 11:21:31 2014)  提到:

    空指针又不是系统挂掉的唯一原因,

    你每次new对象的时候都会去检查异常么?

    【 在 wz911 (晃来晃去) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Mon Mar 17 11:35:06 2014)  提到:

    软件不是只有你说的那一种

    桌面、外包服务软件、内部应用、互联网小规模、大规模服务,对待错误的处理是完全不一样的,不能以偏概全。

    【 在 wz911 (晃来晃去) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     worldinsand (worldinsand) 于  (Mon Mar 17 12:23:40 2014)  提到:

    你觉得代码不ugly重要还是你的饭碗重要?

    【 在 wxsoar 的大作中提到: 】

    ☆─────────────────────────────────────☆

     fonair (fonair) 于  (Mon Mar 17 12:52:58 2014)  提到:

    楼主是新搞开发的吧,你如果不能禁止别人传入null,就得检查是不是null,道理不多说

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     NoSmoking (戒烟) 于  (Mon Mar 17 14:36:06 2014)  提到:

    淡定点,你如果去做几个月测试人员,相信你会明白很多,当然,开发的不屑去干测试

    有句话说的好,你负责开发个产品,测试就是想法搞死你的产品,你管别人怎么搞死的

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     fonair (fonair) 于  (Mon Mar 17 16:29:32 2014)  提到:

    new后不检查,我不知道java是不是有机制保证new 100%成功,但C++绝对没有这个保证

    【 在 javaboy (喝了咖啡就话多-_-;) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     libgcc (*河蟹*) 于  (Mon Mar 17 16:53:06 2014)  提到:

    我觉得c++的new根本不用去检查失败不失败

    系统上跑的程序可能每时每刻都在做无数的new,而且我相信他们大部分都没有检查...

    【 在 fonair (fonair) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     chiefmajia (马甲之王) 于  (Mon Mar 17 17:09:56 2014)  提到:

    其实用不用检查就一条:

    程序能不能通过测试部门的要求。

    【 在 libgcc (*河蟹*) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     fonair (fonair) 于  (Mon Mar 17 17:12:11 2014)  提到:

    你可以保证你的程序没有leak,如果其他人的程序leak了,你的程序就以crash来回应?

    【 在 libgcc (*河蟹*) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     wz911 (晃来晃去) 于  (Tue Mar 18 09:21:57 2014)  提到:

    【 在 Goldhead 的大作中提到: 】

    不同的行业对软件要求肯定不一样,但是你跟说一下,在任何行业里面,你一个平台软件让程序员地崩掉是跟更好的选择,大家都说,嗯,这个地方崩的好,崩的有道理,别跟说说assert,别跟说debug的时候看调用,程序在发布给用户以后你指望用户读这些个东西?那用户就自己开发了,要软件开发公司干嘛。判断出现异常以后会有很多种方法跟踪,崩是最差劲的一种办法,

    ☆─────────────────────────────────────☆

     wz911 (晃来晃去) 于  (Tue Mar 18 09:25:04 2014)  提到:

    【 在 javaboy 的大作中提到: 】

    你说的没错,空指针不是系统挂掉的唯一原因,但是是系统挂掉的主要原因,

    new对象的时候我都要检查,c里面用指针的时候更要好好检查,做软件的小心点不是坏事,

    大家都知道指针好用,可是为什么高级语言里面越来越少,很多语言后来压根就不推荐使用,乃至都封装好了,为啥,就是太灵活,太危险。

    ☆─────────────────────────────────────☆

     wz911 (晃来晃去) 于  (Tue Mar 18 09:30:45 2014)  提到:

    【 在 Tinro 的大作中提到: 】

    对错误处理是不一样,但是有几个原则是一样的,

    1.对可能发现的错误会有分级处理,导致系统/进程挂的是最严重的,然后就是异常输入,分支处理错误,逻辑错误,等等,你如果处理过测试提出的bug你就知道,崩的bug从来都是优先级最高的,也是最无法容忍,也是最难定位的,特别是n久出现一次,偶发,但是长期运行必现的,

    2.软件的容错要求是必须的,怎么实现容错,崩明显不是容错的方法

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Tue Mar 18 09:56:57 2014)  提到:

    你的第一条就错了

    对于互联网来说。进程挂不是最严重的错误,带错运行才是最严重的。

    【 在 wz911 (晃来晃去) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     xshoushoux (xshoushoux) 于  (Tue Mar 18 10:08:59 2014)  提到:

    太绝对了

    别的不说,就标准库里,除了free()大部分都是碰到0指针就崩的

    linux kernel和win32 api也到处都是碰到0指针直接崩的

    这些函数除了极少数都没有performance concern严重到连检查0指针都不允许做

    【 在 wz911 (晃来晃去) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Tue Mar 18 10:37:01 2014)  提到:

    标准里的free和delete对于空指针都是无动作...

    【 在 xshoushoux (xshoushoux) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     wz911 (晃来晃去) 于  (Tue Mar 18 14:50:54 2014)  提到:

    【 在 xshoushoux 的大作中提到: 】

    肯能有点绝对,但是咱们主贴的前提是针对平台,估计还是商业软件,

    linux这个东西之所以流行,一个是因为确实不错,另外一个是因为免费,就编码规范而言,确实感觉一般,

    其实各位感觉不检查也行也无所谓,毕竟我这就一种观点而已,又不是权威,不过遇到指针慎重点是没错的,

    ☆─────────────────────────────────────☆

     wz911 (晃来晃去) 于  (Tue Mar 18 15:11:13 2014)  提到:

    【 在 Tinro 的大作中提到: 】

    你说的互联网太宽泛,而且带错运行更进程挂都是错误,都要避免他们分别有不同的机制来保证,咱们细化一下,好好说说:

    情景1,大型数据库交互流程中,比如股票买卖相关的数据库交互,负责通信的进程挂掉。

    情景2.手机某app 在运行过程中出现错误,导致app挂掉。

    情景3.比如骨干网传输节点中上海与美国海底电缆负责业务转发的服务器或者大型数据交换转发设备故障,

    情景4.发送的业务数据出现错误,比如,目的ip错误,

    情景5,控制逻辑出现错误,

    根据程序运行的环境以及要求,对程序要求是不同的,如果你就是做简单应用,单机游戏之类,程序挂了用户最多骂娘,重启,最多不用你的程序,这个没什么,但是在数据转发设备或者大型通讯设备内部,如果程序挂了搞不好是要死公司的,

    想象一下我最早说的例子,如果发生在北京,那么后果就是一半以上的北京的互联网,手机,宽带,传真,这些业务都会中断,哪怕就一个小时,都不是那个公司能承受的。

    再说一下带错运行,一个程序在编写的时候就要有错误检查机制,包括指针检查,参数检查,等等,还有一种机制叫异常检查,包括程序错配,错连,设备中程序一旦出现异常,或者因为异常导致的业务数据错误,他的上下游节点会发出各种告警,如果你去局方出差你会看到,那种大型的显示屏,出现一系列的信息,声音,节点颜色变化,几分钟内就会有人做出反应。

    在开发程序的时候,每个功能都是要权衡的,包括各种检查,纠错,等等,我的意思是,写代码的时候要慎重,在使用指针的时候多问问,要不要检查,是不是加上更好,这个总是没错的。

    当然,是程序就有bug,程序员的工作是在编写代码的时候或者设计的时候就从逻辑跟流程上尽量避免bug,所以说好软件是设计出来,而不是写出来的,

    如果测试使用各个异常参数进行测试,那么也尽量配合,特别是商业平台软件,提供给其他用户的接口,多测试总归没错的,测试用例设计上,主要你的用户手册没有明确规定说不行的,他都能拿来尝试,毕竟你软件要卖钱,如果不想以后被骂,小心为上。

    最后说一句,如果你去救火面对真正用户的时候,很多时候你是没办法做沟通的,

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Tue Mar 18 15:32:18 2014)  提到:

    你说的这些,1-3显然不能随便挂,其他的有些太笼统

    我也举个例子,搜索引擎后台,处理用户查询的节点一般都有几十几百倍以上的冗余,一台进程挂掉可以立即无缝切换到其他机器;处理检索的节点即使冗余倍数较少,挂掉一台机器最多少几十分之一的数据,对服务的影响微乎其微。关键数据都有更高的冗余度支持。

    你总是说去局方出差什么的,互联网公司根本不需要考虑这个问题。互联网最重要的是快速迭代上线,在速度和质量中间经常是倾向于速度的,偶发的错误都可以通过冗余抗住,然后快速上线修复。根本上这还是 软件开发周期决定的。

    【 在 wz911 (晃来晃去) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     wz911 (晃来晃去) 于  (Tue Mar 18 16:40:32 2014)  提到:

    【 在 Tinro 的大作中提到: 】

    看来是对互联网的理解不同,

    我理解的互联网,在数据方面涵盖数据传输,处理,储存,在服务方面涵盖了金融,证券,电子商务,电话,等等,在互联网中,基础是绝对要保证稳定的,数据处理,储存,传输以及金融等相关服务也必须保持稳定,你意义中的互联网,应该是你做的,比如京东的搜索类业务,这种挂掉没关系,反正可以重新输入,特别是app类软件的开发以及电子商务的产品上线,速度要求是第一的,可以理解,出错了大家也可以采用其他手段规避。

    另外一个角度,就绝对不能挂,必须要是沪深股市交易中的数据损失了百分之一,或者淘宝每天交易数据损失百分之一都是无法接受的。

    不管怎么说,软件少点故障都是好事,,

    ☆─────────────────────────────────────☆

     xixihehaha (forfish) 于  (Fri Mar 21 17:28:57 2014)  提到:

    一般自己的函数都会判断NULL,不知道是否效率高~

    ☆─────────────────────────────────────☆

     summer (戒烟~~Idle) 于  (Mon Mar 31 05:12:51 2014)  提到:

    你们两人打回去重新学C++

    new失败了默认要std::bad_alloc,除非有nothrow

    【 在 libgcc 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Madlee (无竹居士) 于  (Mon Mar 31 10:34:58 2014)  提到:

    所以,该用引用的地方用引用。

    ☆─────────────────────────────────────☆

     ystone (...) 于  (Mon Mar 31 13:22:54 2014)  提到:

    c++, new失败时,默认是抛出异常,检查NULL不行。

    【 在 wxsoar 的大作中提到: 】

    ☆─────────────────────────────────────☆

     mostforce (MF) 于  (Mon Mar 31 17:07:10 2014)  提到:

    如果你的软件面对客户的时候像LINUX和WINDOWS一样强势,那么你可以制定你的规则。但是现实中大多数时间你是弱势,求爷爷告奶奶让客户买你的软件。

    码农就喜欢用一根筋的技术思维去考虑问题。

    【 在 xshoushoux 的大作中提到: 】

    ☆─────────────────────────────────────☆

     kobe2000 (意义) 于  (Tue Apr  1 08:03:26 2014)  提到:

    一根筋往往更容易成就事业

    【 在 mostforce 的大作中提到: 】

    ☆─────────────────────────────────────☆

     mostforce (MF) 于  (Tue Apr  1 08:54:12 2014)  提到:

    如果事事一根筋,和成就事业就差几光年了。

    【 在 kobe2000 的大作中提到: 】

    ☆─────────────────────────────────────☆

     xshoushoux (xshoushoux) 于  (Tue Apr  1 09:01:31 2014)  提到:

    和他们是否强势没啥关系,比如memcpy,你作为客户难道希望它在接到null指针参数的

    时候返回个错误码给你,然后你得在每次调用memcpy的时候检查返回值?如果它真这样

    做的话才是给客户找麻烦吧,客户八成得骂娘。。。

    【 在 mostforce (MF) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Tue Apr  1 09:06:04 2014)  提到:

    程序设计语言有两种设计哲学:

    一种认为程序员应该知道他们在干什么,代表性的比如C/C++

    一种认为程序员其实不知道他们在干什么,代表性的比如Java

    【 在 xshoushoux (xshoushoux) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     kobe2000 (意义) 于  (Tue Apr  1 09:21:00 2014)  提到:

    真不知道有多少cpp程序员能够回答14589的问题

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     treetoad (蚊子) 于  (Tue Apr  1 09:40:30 2014)  提到:

    说了这半天,就是调用者的问题啊,测试人员也有责任

    难道测试过程中,不测试“重启”这种场景么?  是不是根本就没测试啊

    【 在 wz911 (晃来晃去) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     kobe2000 (意义) 于  (Tue Apr  1 09:52:37 2014)  提到:

    他这个是循环论证,把文章里的0改成1,也都说的通,结论是:必须检查1指针

    【 在 treetoad (蚊子) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     wz911 (晃来晃去) 于  (Tue Apr  1 10:31:14 2014)  提到:

    【 在 treetoad 的大作中提到: 】

    重启肯定要测试,带业务的,但是测试从来都不能覆盖全部场景的。

    但是在某种情况下(特定业务组合),这种组合导致的重启,而且这种业务组合又是合理的配置,这种条件依靠系统测试肯定是不行,

    写代码这么马虎,单元测试肯定也没做好,代码review有没有走都两说,

    ☆─────────────────────────────────────☆

     irreallich (lich) 于  (Tue Apr  1 12:23:31 2014)  提到:

    首先要做好自己的事情,特别是成本不高的时候

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     iclass (iclass) 于  (Tue Apr  1 15:44:10 2014)  提到:

    楼主这样的还是公司的开发人员,贵公司软件质量堪忧

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自

    然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起

    去!

    ☆─────────────────────────────────────☆

     codeage (codeage) 于  (Thu Apr  3 10:52:37 2014)  提到:

    查阅一下“契约式编程”的概要以及背后思想

    随便搜了个链接给你

    http://www.cnblogs.com/steady/archive/2012/05/03/2481024.html

    这是软件工程问题,而不是编程语言本身要解决的问题

    基本思想是,提供的组件光有程序接口和背后的功能,是不够的。必须还要使用者和功能提供者双方共同履行的使用契约。加起来才是完整的可复用组件。

    你让测试人员也看下,然后双方共同约定一下接口使用规范。一般而言,一些很明显的异常情况是需要检测的。只不过是if (ptr==null) 还是 assert(ptr!=null) 区分了是义务还是权力的问题。我长期从事复用模块提供者的工作,经验是能尽早报告的异常就尽量尽早报告。怎么处理是第二位的。

    现实情况下,你应该尽量和组件使用者一起达成契约。这本身就是开发中很重要的事。

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     guanshuiyong (老东西) 于  (Thu Apr  3 22:22:21 2014)  提到:

    多写了个*,为0指针,这是巧合吧,也有可能是2、3、0xf37ef89a、……等等

    【 在 wz911 (晃来晃去) 的大作中提到: 】

    【 在 wxsoar (嘿嘿) 的大作中提到: 】

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应�

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应该由调用者进行保证,而不应该将问题提给函数的实现者

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应该由调用者进行保证,而不应该将问题提给函数的实现者

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应该由调用者进行保证,而不应该将问题提给函数的实现者

    : ...................

    : 开源的程序一般都是将这个交由调用者来做的,很多代码甚至没有输入检查,这是因为开源的东西一般都是大牛在整。

    : 而公司的商业开发最好要做输入检查,员工参差不齐,大家重视的是KPI什么的,不能保证每个程序员都有很高的水准,或者对他要调用的东西有深入的理解。

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*

    : ...................

    : 检查了,代码不会很ugly吗,难道还要继续判断不为-1,-2……吗,那代码该怎样写?

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应�

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应�

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应�

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : &nbsp;&nbsp;

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应该由调用者进行保证,而不应该将问题提给函数的实现者

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入

    : ...................

    : 支持不检测,除非0是一个有约定的特殊输入

    : 修改一下:按照约定来做。约定调用者来检查就调用者检查。

    : ==================================

    : 如果ptr可能是NULL,应该代码要处理。

    : ...................

    : 你写清楚传入非法值会crash on purpose就好了

    : 标  题: Re: 在C/C++语言中,检测指针是否为NULL有意义吗?

    : 发信站: 水木社区 (Sat Mar 15 11:35:30 2014), 站内

    : 这是个好主意,可是开始并没有写啊,现在去加他们又不干

    : 另,在c语言中,使用非法指针,

    : 结果无法预期,难道不是语言自身的规则吗

    : 【 在 PGP 的大作中提到: 】

    : : 你写清楚传入非法值会crash on purpose就好了

    : :

    : --

    : ...................

    :如果你写的这个库也向stdlib一样的应用范围,可以直接无视测试人员,

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应�

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : ...................

    : 标  题: Re: 在C/C++语言中,检测指针是否为NULL有意义吗?

    : 发信站: 水木社区 (Sat Mar 15 11:56:58 2014), 站内

    : 求解释

    : ---------------------------

    : 【 在 liuxueshen 的大作中提到: 】

    : : ...................

    : :如果你写的这个库也向stdlib一样的应用范围,可以直接无视测试人员,

    : --

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应该由调用者进行保证,而不应该将问题提给函数的实现者

    : ...................

    : 恩,我也觉得十分SB

    : 给个指针变量那SB非要传个非法值进来,那不是找贱么,不过总是有这样的人。

    : 我觉得检测下== 0/NULL 就好,可以应付大部分出错了。一般也就是调用方疏忽了,或者上一次函数调用让指针变为NULL了。

    : ...................

    : 我觉得大部分码农写代码的时候,也不是在调用函数前,先检查一下调用参数是否非法,而是在函数里面,检查参数范围。写库难道不是这样?

    : 我觉得大部分码农写代码的时候,也不是在调用函数前,先检查一下调用参数是否非法,而是在函数里面,检查参数范围。写库难道不是这样?

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应该由调用者进行保证,而不应该将问题提给函数的实现者

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应�

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应该由调用者进行保证,而不应该将问题提给函数的实现者

    : ...................

    : 很多时候不是讲道理就能行得通的。

    : 假设如下一个情况:你们公司是卖库的,库的潜在用户有高手有菜鸟,是菜鸟用户试用你们的库的时候不小心传递了一个null给api函数因为你没有检查程序崩了,你就有可能失去了这个客户,他不认为是自己的错,可能认为是你们的库不够稳定不够安全。 如果你检查了null指针,并

    : 不要把用户想得和你一样牛,你要把用户想成白痴,

    : ...................

    : 当然有必要,给你说个真实的例子,某设备商的设备,开发人员在调用平台接口的时候参数多写了个*导致指针引用错误,0指针导致cpu复位,不幸的是测试没有覆盖到,最后发给运营商,更不幸的是准入测试也没有覆盖到,然后业务切换,一切正常,某天,某个功能引发这个问题,�

    : 这种后果你想过么???

    : 现在再回答一下这个问题,指针为0需要检查么?

    : 真把用户想成白痴的话,你觉得他会好好检查你函数的返回值吗?

    : 静悄悄地返回一个错误码,还不如core dump来得好

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应该由调用者进行保证,而不应该将问题提给函数的实现者

    : ...................

    : 真把用户想成白痴的话,你觉得他会好好检查你函数的返回值吗?

    : 静悄悄地返回一个错误码,还不如core dump来得好

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : ...................

    : 大哥,程序的健壮性,最基本的一条要求就是跨模块要查参数的

    : 还是这个例子,如果不检查NULL,直接CORE DUMP,菜鸟检查代码,调试,发现是传递了NULL指针导致的,很多菜鸟直接会这么想:什么垃圾库,连空指针都不检查都导致崩溃。

    : 如果对于NULL返回一个错误代码,但是菜鸟没有检查这个错误代码,所以接下来继续操作调用别的API,因为上一个API调用已经失败,所以接下来的API也会失败,最后他的需要的功能不能正常工作, 他只好回头检查代码,检查返回值,看文档,最后发现是自己问题,那么他的印象和�

    : 假设有两个公司卖的开发包分别是用以上两种方式来处理NULL指针,大多数菜鸟用户会选择购买哪个库?(假设其他功能都同等的情况下)

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入

    : ...................

    : 还是这个例子,如果不检查NULL,直接CORE DUMP,菜鸟检查代码,调试,发现是传递了NULL指针导致的,很多菜鸟直接会这么想:什么垃圾库,连空指针都不检查都导致崩溃。

    : 如果对于NULL返回一个错误代码,但是菜鸟没有检查这个错误代码,所以接下来继续操作调用别的API,因为上一个API调用已经失败,所以接下来的API也会失败,最后他的需要的功能不能正常工作, 他只好回头检查代码,检查返回值,看文档,最后发现是自己问题,那么他的印象和�

    : 假设有两个公司卖的开发包分别是用以上两种方式来处理NULL指针,大多数菜鸟用户会选择购买哪个库?(假设其他功能都同等的情况下)

    : ...................

    : 标准库也不会检查的,也没看谁抱怨

    : 标准库也不会检查的,也没看谁抱怨

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应�

    : ...................

    : 很多时候不是讲道理就能行得通的。

    : 假设如下一个情况:你们公司是卖库的,库的潜在用户有高手有菜鸟,是菜鸟用户试用你们的库的时候不小心传递了一个null给api函数因为你没有检查程序崩了,你就有可能失去了这个客户,他不认为是自己的错,可能认为是你们的库不够稳定不够安全。 如果你检查了null指针,并返回一个特定的值,比如自己定义的枚举类型:eptrnull,这个菜鸟看了返回值就明白了。

    : 不要把用户想得和你一样牛,你要把用户想成白痴,

    : ...................

    : 还是这个例子,如果不检查NULL,直接CORE DUMP,菜鸟检查代码,调试,发现是传递了NULL指针导致的,很多菜鸟直接会这么想:什么垃圾库,连空指针都不检查都导致崩溃。

    : 如果对于NULL返回一个错误代码,但是菜鸟没有检查这个错误代码,所以接下来继续操作调用别的API,因为上一个API调用已经失败,所以接下来的API也会失败,最后他的需要的功能不能正常工作, 他只好回头检查代码,检查返回值,看文档,最后发现是自己问题,那么他的印象和上一个完全是两回事:这个库挺不错的,函数直接返回了错误代码告诉我哪里出了问题。

    : 假设有两个公司卖的开发包分别是用以上两种方式来处理NULL指针,大多数菜鸟用户会选择购买哪个库?(假设其他功能都同等的情况下)

    : ...................

    : 检查了,代码不会很ugly吗,难道还要继续判断不为-1,-2……吗,那代码该怎样写?

    : 没有文档说明,请老大搞定,这已经超出你的能力范围了;

    : 老大搞不定,继续找上层,这不属于技术范畴了,属于代码分工。

    : 语言自身规则要保证多数应用情况,

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应�

    : ...................

    : 恩,我也觉得十分SB

    : 给个指针变量那SB非要传个非法值进来,那不是找贱么,不过总是有这样的人。

    : 我觉得检测下== 0/NULL 就好,可以应付大部分出错了。一般也就是调用方疏忽了,或者上一次函数调用让指针变为NULL了。

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应�

    : ...................

    : 针对每一个函数写一个 入口检查函数

    : matlab就这么搞得

    : 比如  void DoSomething(int a, int b)

    : ...................

    : visual studio有没有编译选项 自动生成参数检查的代码?这样在release/debug下面都能保证传入非法null参数,程序立刻崩溃

    : 编译器哪儿敢假定哪个指针参数允许 NULL 哪个又不允许的?

    : 我就随便问问。不过为什么不可以假定呢? 完全可以添加这个编译选项。我觉得楼主的意思他们的库都认为传入null是非法的,如果编译器提供这样的选项,直接对参数指针在debug下加assert,再release下直接嵌入句汇编判断。。那么,楼主只要打开这个编译开关编译出程序给测�

    : 函数设计,基本要求就是 传入合法的能得到合法结果,传入非法的得到非法结果抛异常或者崩溃就行啊。

    : 最怕的是,传入合法或者非法的参数,你给人家一个ub的飘忽不定的结果。。

    : 我只能认同一半。

    : 一个函数,传入合法的参数,一定要得到合法的结果。其实做到这步都很难,可移植性以及跨平台,还有线程安全,等等。

    : 至于另一半,我认为点到为止即可,事实上,我认为完全可靠的函数是没有的,即使你设计再多的输入检查。

    : ...................

    : 这种事为什么不用宏呢……

    : 自动化也是插桩工具比较自然吧?

    : 说个题外话,记得linus好像喷过glibc的memcpy实现,他说kernel里memcpy直接就是做

    : 成memmove的alias,然后说glibc也应该这么办

    : 导火线是glibc的memcpy某个版本的改动导致adobe flash出了问题(flash里有一个

    : ...................

    : 说个题外话,记得linus好像喷过glibc的memcpy实现,他说kernel里memcpy直接就是做

    : 成memmove的alias,然后说glibc也应该这么办

    : 导火线是glibc的memcpy某个版本的改动导致adobe flash出了问题(flash里有一个

    : ...................

    : 挺有意思,linus似乎是个隐藏的喷神,还喷过debug

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应该由调用者进行保证,而不应该将问题提给函数的实现者

    : ...................

    : assert就是宏

    : visual studio有没有编译选项 自动生成参数检查的代码?这样在release/debug下面都能保证传入非法null参数,程序立刻崩溃,就一句判断是否为null的代码,对函数性能影响不大吧

    : 检查NULL也不能解决这个问题。

    : 在那个故障问题如果加了NULL检查,至少能保证不会全系统重启,业务倒换失败的问题虽然严重,但是还是可控,如果整个系统挂掉,如果你有去局方出差的经历,你就会知道后果有多严重,

    : 在软件设计过程中除了极少数模块对性能要求极其高的情况下,会对参数的检查做某些妥协,一般软件特别是平台软件都要求接口处对参数做相当的校验,比如指针是否为空,参数是否在克里范围内还有些设计要求在正式配置之前要有test配置过程,

    : 参数检查从来都不能解决所有问题,但是能有效减少致命问题的出现可能,你明知道空指针必然导致系统挂掉,还非说不能解决所有问题,不做任何检查,这点都意识都没有的话,你就别做软件了,压根就不是做软件的材料,也没有能力开发稍微大型一点的软件。

    : ...................

    : 在那个故障问题如果加了NULL检查,至少能保证不会全系统重启,业务倒换失败的问题虽然严重,但是还是可控,如果整个系统挂掉,如果你有去局方出差的经历,你就会知道后果有多严重,

    : 在软件设计过程中除了极少数模块对性能要求极其高的情况下,会对参数的检查做某些妥协,一般软件特别是平台软件都要求接口处对参数做相当的校验,比如指针是否为空,参数是否在克里范围内还有些设计要求在正式配置之前要有test配置过程,

    : 参数检查从来都不能解决所有问题,但是能有效减少致命问题的出现可能,你明知道空指针必然导致系统挂掉,还非说不能解决所有问题,不做任何检查,这点都意识都没有的话,你就别做软件了,压根就不是做软件的材料,也没有能力开发稍微大型一点的软件。

    : ...................

    : 在那个故障问题如果加了NULL检查,至少能保证不会全系统重启,业务倒换失败的问题虽然严重,但是还是可控,如果整个系统挂掉,如果你有去局方出差的经历,你就会知道后果有多严重,

    : 在软件设计过程中除了极少数模块对性能要求极其高的情况下,会对参数的检查做某些妥协,一般软件特别是平台软件都要求接口处对参数做相当的校验,比如指针是否为空,参数是否在克里范围内还有些设计要求在正式配置之前要有test配置过程,

    : 参数检查从来都不能解决所有问题,但是能有效减少致命问题的出现可能,你明知道空指针必然导致系统挂掉,还非说不能解决所有问题,不做任何检查,这点都意识都没有的话,你就别做软件了,压根就不是做软件的材料,也没有能力开发稍微大型一点的软件。

    : ...................

    : 检查了,代码不会很ugly吗,难道还要继续判断不为-1,-2……吗,那代码该怎样写?

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : ...................

    : 空指针又不是系统挂掉的唯一原因,

    : 你每次new对象的时候都会去检查异常么?

    : new后不检查,我不知道java是不是有机制保证new 100%成功,但C++绝对没有这个保证

    : 我觉得c++的new根本不用去检查失败不失败

    : 系统上跑的程序可能每时每刻都在做无数的new,而且我相信他们大部分都没有检查...

    : 我觉得c++的new根本不用去检查失败不失败

    : 系统上跑的程序可能每时每刻都在做无数的new,而且我相信他们大部分都没有检查...

    : 太绝对了,不同domain情况不一样

    : 在你那儿也许尽最大可能让程序不崩是最高的优先级,但也有很多场景下让程序原地崩掉

    : 是更好的选择

    : ...................

    : 空指针又不是系统挂掉的唯一原因,

    : 你每次new对象的时候都会去检查异常么?

    : 软件不是只有你说的那一种

    : 桌面、外包服务软件、内部应用、互联网小规模、大规模服务,对待错误的处理是完全不一样的,不能以偏概全。

    : 对错误处理是不一样,但是有几个原则是一样的,

    : 1.对可能发现的错误会有分级处理,导致系统/进程挂的是最严重的,然后就是异常输入,分支处理错误,逻辑错误,等等,你如果处理过测试提出的bug你就知道,崩的bug从来都是优先级最高的,也是最无法容忍,也是最难定位的,特别是n久出现一次,偶发,但是长期运行必现的,

    : 2.软件的容错要求是必须的,怎么实现容错,崩明显不是容错的方法

    : ...................

    : 不同的行业对软件要求肯定不一样,但是你跟说一下,在任何行业里面,你一个平台软件让程序员地崩掉是跟更好的选择,大家都说,嗯,这个地方崩的好,崩的有道理,别跟说说assert,别跟说debug的时候看调用,程序在发布给用户以后你指望用户读这些个东西?那用户就自己开�

    : 太绝对了

    : 别的不说,就标准库里,除了free()大部分都是碰到0指针就崩的

    : linux kernel和win32 api也到处都是碰到0指针直接崩的

    : ...................

    : 太绝对了

    : 别的不说,就标准库里,除了free()大部分都是碰到0指针就崩的

    : linux kernel和win32 api也到处都是碰到0指针直接崩的

    : ...................

    : 你的第一条就错了

    : 对于互联网来说。进程挂不是最严重的错误,带错运行才是最严重的。

    : 你说的互联网太宽泛,而且带错运行更进程挂都是错误,都要避免他们分别有不同的机制来保证,咱们细化一下,好好说说:

    : 情景1,大型数据库交互流程中,比如股票买卖相关的数据库交互,负责通信的进程挂掉。

    : 情景2.手机某app 在运行过程中出现错误,导致app挂掉。

    : ...................

    : 你说的这些,1-3显然不能随便挂,其他的有些太笼统

    : 我也举个例子,搜索引擎后台,处理用户查询的节点一般都有几十几百倍以上的冗余,一台进程挂掉可以立即无缝切换到其他机器;处理检索的节点即使冗余倍数较少,挂掉一台机器最多少几十分之一的数据,对服务的影响微乎其微。关键数据都有更高的冗余度支持。

    : 你总是说去局方出差什么的,互联网公司根本不需要考虑这个问题。互联网最重要的是快速迭代上线,在速度和质量中间经常是倾向于速度的,偶发的错误都可以通过冗余抗住,然后快速上线修复。根本上这还是 软件开发周期决定的。

    : ...................

    : 我觉得c++的new根本不用去检查失败不失败

    : 系统上跑的程序可能每时每刻都在做无数的new,而且我相信他们大部分都没有检查...

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应该由调用者进行保证,而不应该将问题提给函数的实现者

    : ...................

    : 太绝对了

    : 别的不说,就标准库里,除了free()大部分都是碰到0指针就崩的

    : linux kernel和win32 api也到处都是碰到0指针直接崩的

    : ...................

    : 如果你的软件面对客户的时候像LINUX和WINDOWS一样强势,那么你可以制定你的规则。但是现实中大多数时间你是弱势,求爷爷告奶奶让客户买你的软件。

    : 码农就喜欢用一根筋的技术思维去考虑问题。

    : 一根筋往往更容易成就事业

    : :

    : 如果你的软件面对客户的时候像LINUX和WINDOWS一样强势,那么你可以制定你的规则。但是现实中大多数时间你是弱势,求爷爷告奶奶让客户买你的软件。

    : 码农就喜欢用一根筋的技术思维去考虑问题。

    : 和他们是否强势没啥关系,比如memcpy,你作为客户难道希望它在接到null指针参数的

    : 时候返回个错误码给你,然后你得在每次调用memcpy的时候检查返回值?如果它这样做

    : 的话才是给客户找麻烦吧。。。

    : ...................

    : 程序设计语言有两种设计哲学:

    : 一种认为程序员应该知道他们在干什么,代表性的比如C/C++

    : 一种认为程序员其实不知道他们在干什么,代表性的比如Java

    : ...................

    : 当然有必要,给你说个真实的例子,某设备商的设备,开发人员在调用平台接口的时候参数多写了个*导致指针引用错误,0指针导致cpu复位,不幸的是测试没有覆盖到,最后发给运营商,更不幸的是准入测试也没有覆盖到,然后业务切换,一切正常,某天,某个功能引发这个问题,导致整个设备重启,更不幸的事情发生了,这种状态的重启也触发这个问题,业务切换动作扩散,导致某个城市的某款设备的某个版本的软件不停复位,耗时几个小时,全部相关网络瘫痪,电话,宽带,手机,

    : 这种后果你想过么???

    : 现在再回答一下这个问题,指针为0需要检查么?

    : 说了这半天,就是调用者的问题啊,测试人员也有责任

    : 难道测试过程中,不测试“重启”这种场景么?  是不是根本就没测试啊

    : 说了这半天,就是调用者的问题啊,测试人员也有责任

    : 难道测试过程中,不测试“重启”这种场景么?  是不是根本就没测试啊

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类

    : ...................

    : 今天和测试人员发生强烈争论,是关于指针的

    : 我们是开发方,设计了一个二次开发的函数库,其中有很多参数需要调用者传入char*类型指针作为参数,结果测试人员设计了很多指针值等于NULL的样本进行测试,测试程序自然而然的发生了崩溃给我们报了很多严重问题,我们去交涉,结果怎么着都说不到一起去!

    : 我的观点是,在C/C++语言中,NULL只是一个普通的非法指针,除非和调用方有特殊约定,否则检查其根本没有意义的,因为作为指针,有太多的非法情况,它可以是没初始化的,也可以是已经被释放了的。被调用的函数,是根本没办法检测指针是合法还是非法的,指针的正确与否应�

    : ...................

    : 当然有必要,给你说个真实的例子,某设备商的设备,开发人员在调用平台接口的时候参数多写了个*导致指针引用错误,0指针导致cpu复位,不幸的是测试没有覆盖到,最后发给运营商,更不幸的是准入测试也没有覆盖到,然后业务切换,一切正常,某天,某个功能引发这个问题,�

    : 这种后果你想过么???

    : 现在再回答一下这个问题,指针为0需要检查么?

    : ...................

    2017-05-14
  • [合集] 写库,弄很多异常,是不负责任的表现

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Mon Mar 17 15:01:34 2014)  提到:

    直接用错误代码就行了 非要整个异常 把程序弄崩溃了

    ☆─────────────────────────────────────☆

     xpay (xpay) 于  (Mon Mar 17 15:57:25 2014)  提到:

    所以你的名字叫牛逼,发明 C++ 异常的是傻逼,定义 <stdexcept> 里面那些异常

    的也是傻逼

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Mon Mar 17 18:15:06 2014)  提到:

    其实我也这么觉得。。。C++异常根本就是sb

    【 在 xpay (xpay) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     iamape (iamape) 于  (Mon Mar 17 18:24:56 2014)  提到:

    写很多是不好,不过不能被忽略的错误抛出异常也不是什么不好的事

    【 在 Tinro (老天若) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Mon Mar 17 19:21:37 2014)  提到:

    抛出异常破坏第一现场

    【 在 iamape (iamape) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     PGP (---) 于  (Mon Mar 17 20:21:13 2014)  提到:

    可恢复的才用异常,其他都是crash

    【 在 Tinro (老天若) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     dami2013 (大米) 于  (Mon Mar 17 22:35:27 2014)  提到:

    C++异常应该用在那些无法返回错误码的地方,比如 operator[]()重载函数里,能用错误码表示的,尽量还是用C方式的错误码吧

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Tue Mar 18 07:43:58 2014)  提到:

    我个人觉得从软件工程的角度而言返回错误码是一个不太好的设计。用起来繁琐不说,更严重的问题是允许调用者忽略错误码。一个很大的软件公司,招的都是很好的码农,有人对codebase做过统计,代码里面95%以上的需要检查的返回值的错误码都没有得到检查。

    比较好的方法就是使用expcetion,同时要求caller能够做到exception safe,比如用smart pointer,比如用RAII之类的。其实养成习惯之后,这些都很方便的。比如不用new和delete,而是用容器;比如new的指针用unique或者shared包起来,这样反而省了一行delete,何乐而不为呢?

    【 在 dami2013 (大米) 的大作中提到: 】

    C++异常应该用在那些无法返回错误码的地方,比如 operator[]()重载函数里,能用错误码表示的,尽量还是用C方式的错误码吧

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Tue Mar 18 09:55:42 2014)  提到:

    operator[]() 在debug模式 进行输入检测 非法输入 就返回一个无意义的结果 然后错误码用内部log写出 或者打印屏幕 同时喇叭嘟嘟响

    debug模式 就不管了 该崩溃就崩溃

    我就这么做的

    【 在 dami2013 的大作中提到: 】

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Tue Mar 18 09:58:49 2014)  提到:

    异常是万不得已才用

    【 在 xpay 的大作中提到: 】

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Tue Mar 18 10:02:16 2014)  提到:

    expcetion 直接到log 或者大喇叭报警  而不是把程序给非法操作了

    比如 用 throw xxx  就写成  ErrorLog << "tmd error!"

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Tue Mar 18 10:19:15 2014)  提到:

    log并不能取代exception。除非LOG(FATAL) << ...,否则程序还是继续得到执行(如果caller没有检查返回值),导致错误继续积累下去。

    而log(fatal)强制crash并不总是是最好的解决方案。因为有的时候错误不是致命的。比如一个server,由于query其他service的时候timeout了所以handle不了这个request,这样的错误至少不是致命的,还可以handle别的request。一个clean的方法就是在这里throw在request handler的最上面catch就好了。如果在一个很深的调用里面把错误码一层一层传上去,实在太恶心了。

    还有人说C++的exception不能有stack trace的信息,这个也是不对的。我看过有人写过一个.so,具体细节我不太清楚了,大致上是重新实现了C++ exception handling的ABI, 让它包含stacktrace的信息。然后LD_PRELOAD加载这个so的程序就可以有stacktrace了。可惜的是我找不到这个东西了。哪位知道的可以告诉我。

    【 在 BrightLiang (WenQiang Xu@米国) 的大作中提到: 】

    expcetion 直接到log 或者大喇叭报警  而不是把程序给非法操作了

    比如 用 throw xxx  就写成  ErrorLog << "tmd error!"

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     xpay (xpay) 于  (Tue Mar 18 10:21:17 2014)  提到:

    fprintf(stderr, ...) 返回错误怎么办?

    【 在 BrightLiang (WenQiang Xu@米国) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Tue Mar 18 10:24:43 2014)  提到:

    即使有stacktrace,你能把所有局部变量的结果都存下来么?

    第一现场是最重要的

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Tue Mar 18 10:30:47 2014)  提到:

    你没法说服C程序员...

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Tue Mar 18 10:42:15 2014)  提到:

    我其实不太理解你所说的第一现场。

    如果是throw的地方,你完全可以把需要的信息log(error)出来再throw,或者如果catch的地方需要这些值,可以把需要的信息加到exception里面去。

    如果是caller的地方,你也可以catch然后log再rethrow。毕竟如果用错误码的话,你anyway也需要有一段代码log(error)这个所谓的第一现场的。所以exception的工作量并不比错误码大,好处是在一个很深的调用里面,在你不需要第一现场的层上,完全不需要有error handling的代码。你甚至可以用SCOPE_EXIT来实现打印第一现场而不需要catch和rethrow。

    【 在 Tinro (老天若) 的大作中提到: 】

    即使有stacktrace,你能把所有局部变量的结果都存下来么?

    第一现场是最重要的

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     chiefmajia (马甲之王) 于  (Tue Mar 18 10:44:12 2014)  提到:

    他需要的是dump一个core文件

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     milksea (肥了,又肥了 >>>_<<<) 于  (Tue Mar 18 10:51:00 2014)  提到:

    他就是要把程序弄死,要那个 core dump

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Tue Mar 18 10:52:02 2014)  提到:

    好吧,我以为他说的是不杀进程的情况。不过貌似不杀进程用可以dump,只不过可能比log(error) heavy,毕竟要把整个memory写到文件里?

    【 在 chiefmajia (马甲之王) 的大作中提到: 】

    他需要的是dump一个core文件

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Tue Mar 18 10:53:19 2014)  提到:

    那不就直接好了crash了,错误码也没啥用了。

    【 在 milksea (肥了,又肥了 >>>_<<<) 的大作中提到: 】

    他就是要把程序弄死,要那个 core dump

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Tue Mar 18 11:08:35 2014)  提到:

    如果在一个很深的调用里面把错误码一层一层传上去,实在太恶心了。

    为啥要传上去?

    你这个就类似 国家信访办 全国人往那里跑 累死了

    问题解决在当地 如果解决不了 写log  然后往上级传一个概括性制的代码就行了 不需要传“李村的村长抢占了王家的地皮”这种具体信息  而是传“出问题了,参考log,不是致命问题,不用维稳”

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Tue Mar 18 11:11:11 2014)  提到:

    不杀进程 dump 怎么做?

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Tue Mar 18 11:12:08 2014)  提到:

    还有人说C++的exception不能有stack trace的信息,这个也是不对的。我看过有人写过一个.so,具体细节我不太清楚了

    标准库有么?

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Tue Mar 18 11:12:09 2014)  提到:

    对。不同的情况下处理方式不一样,客户端或者大型单点服务肯定不能这么做,但对高冗余的服务这么做最简单直接,进程crash的代价一点也不大,反而是如果带错运行hang住代价更大。

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Tue Mar 18 11:23:37 2014)  提到:

    这个和标准库没有关系,是替换原有的abi。对于程序本身是透明的。程序不用做任何修改,甚至不需要重新编译就可以直接运行。

    当然你程序不做修改就打印不了stacktrace吧。具体细节不记得了,几年前看到过的。你可以认为它还实现了一个函数vector<vector<string>> getStackTrace(std::exception& e);之类的。这个确实不是标准库里的东西。

    【 在 BrightLiang (WenQiang Xu@米国) 的大作中提到: 】

    还有人说C++的exception不能有stack trace的信息,这个也是不对的。我看过有人写过一个.so,具体细节我不太清楚了

    标准库有么?

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Tue Mar 18 11:25:05 2014)  提到:

    先fork再dump

    【 在 BrightLiang (WenQiang Xu@米国) 的大作中提到: 】

    不杀进程 dump 怎么做?

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Tue Mar 18 11:29:04 2014)  提到:

    即使用概括性的,那你也得

    bool f() {

    // blablabla

    if (!doSomething()) {

    return false;

    }

    // blablabla

    if (!doSomething2()) {

    return false;

    }

    // blablabla

    if (!doSomething3()) {

    return false;

    }

    // blablabla

    return true;

    }

    bool g() {

    // blablabla

    if (!f()) {

    reutrn false;

    }

    // blablabla

    if (!doSomething4()) {

    return false;

    }

    // blablabla

    return true;

    }

    写起来恶心不说,性能也更慢。用exception直接就是

    void f() {

    // blablabla

    doSomething();

    // blablabla

    doSomething2();

    // blablabla

    doSomething3();

    // blablabla

    }

    void g() {

    // blablabla

    f();

    // blablabla

    doSomething4();

    // blablabla

    }

    【 在 BrightLiang (WenQiang Xu@米国) 的大作中提到: 】

    如果在一个很深的调用里面把错误码一层一层传上去,实在太恶心了。

    为啥要传上去?

    你这个就类似 国家信访办 全国人往那里跑 累死了

    问题解决在当地 如果解决不了 写log  然后往上级传一个概括性制的代码就行了 不需要传“李村的村长抢占了王家的地皮”这种具体信息  而是传“出问题了,参考log,不是致命问题,不用维稳”

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Tue Mar 18 11:34:01 2014)  提到:

    dump为什么要杀进程?

    【 在 BrightLiang (WenQiang Xu@米国) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     dami2013 (大米) 于  (Tue Mar 18 12:16:01 2014)  提到:

    神马软件工程啊,有空多写代码吧

    错误处理方式有返回错误码,有longjump,有异常

    每种错误处理方式出来都不是对前面那种方式的代替,而是补充

    你要觉得返回错误码麻烦,那么异常就更加麻烦了

    最后麻烦你多写代码少放空炮,不懂不要误导别人

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     PGP (---) 于  (Tue Mar 18 12:36:25 2014)  提到:

    你给举一个异常比返回错误码麻烦的例子?

    【 在 dami2013 (大米) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Tue Mar 18 12:41:58 2014)  提到:

    觉得异常比错误码麻烦的,足下的审美颇为奇特。

    说我放空炮,我当码农也有些年头了,这些是从我的写过的和review过的许多代码,听过的 公司里世界级C++大牛上课的里总结的各种经验。

    至少我列了几条理由,说明错误码在现实中的问题。现实就是,即使是很好的软件公司和很优秀的码农,照样会不去处理错误码,更不要说那些一般般的码农了。没有开发经验的人才会觉得整个函数都是错误码处理的code会比较好维护,会产生质量更好的代码。而你只是武断下了几个结论而已,谁放空炮显而易见。

    至于替代还是补充。新的feature把老的coding style deprecate掉是很正常的事情。到底是补充还是替代不是你说了算的。只要不是滥用,比如用来做flow control,而是把exception用到确实发生错误了的地方,适当多用是没有问题。

    最后,原话还给你:最后麻烦你多写代码少放空炮,不懂不要误导别人

    【 在 dami2013 (大米) 的大作中提到: 】

    神马软件工程啊,有空多写代码吧

    错误处理方式有返回错误码,有longjump,有异常

    每种错误处理方式出来都不是对前面那种方式的代替,而是补充

    你要觉得返回错误码麻烦,那么异常就更加麻烦了

    最后麻烦你多写代码少放空炮,不懂不要误导别人

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     openyy (openyy) 于  (Tue Mar 18 14:02:39 2014)  提到:

    异常显然比错误码麻烦.

    错误码返回类型void就不用处理返回值.

    用异常你就不知道.

    错误码,下层的错误你不处理就不处理了.

    异常,下层异常你不捕获就扔上面去了.

    错误码处理写几句,异常处理也要写几句.

    那种最后一个大try/catch的做法,和出错不处理,没啥区别.

    抛异常通常都是懒人做法,意思就是爱谁谁,哥不管了.

    返回错误码通常是负责任的做法,

    意思是哥把能处理得都处理了, 剩下的俺通知你了.反正调用是失败了.

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     aqhistory (江小坏) 于  (Tue Mar 18 14:21:26 2014)  提到:

    你后面说的,是现代c++推荐的。

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Tue Mar 18 14:29:07 2014)  提到:

    “下层的错误你不处理就不处理了.”可以被忽略的错误本来就不需要用异常。问题是大多数时候错误都不该被忽略。出了问题不去处理,程序还在按照正常情况的逻辑去执行,不出问题才怪呢。

    “错误码处理写几句,异常处理也要写几句.”笑话。错误码每个地方都要检查返回值。异常只需要在最上面写一遍就行了。

    “那种最后一个大try/catch的做法,和出错不处理,没啥区别.”当然有区别。“出错不处理”那是带错运行。“一个大try/catch”至少保证没有带错运行。在server里面,在最上面try catch,我能保证当前session及时终止,没有带错运行,资源正确释放。然后根据exeption的严重程度,决定是不是处理下一个session,还是终止程序。再说,你错误码能携带多少信息给上层?Exception又能携带多少信息给上层?孰优孰劣一目了然。

    “抛异常通常都是懒人做法,意思就是爱谁谁,哥不管了.

    返回错误码通常是负责任的做法,

    意思是哥把能处理得都处理了, 剩下的俺通知你了.反正调用是失败了.”

    完全说反了,“错误处理”才是懒人的做法,你爱谁谁,我不管了。

    “异常处理”强制上面的人必须处理,不能随便对待这个问题,才是负责人的做法。

    【 在 openyy (openyy) 的大作中提到: 】

    异常显然比错误码麻烦.

    错误码返回类型void就不用处理返回值.

    用异常你就不知道.

    错误码,下层的错误你不处理就不处理了.

    异常,下层异常你不捕获就扔上面去了.

    错误码处理写几句,异常处理也要写几句.

    那种最后一个大try/catch的做法,和出错不处理,没啥区别.

    抛异常通常都是懒人做法,意思就是爱谁谁,哥不管了.

    返回错误码通常是负责任的做法,

    意思是哥把能处理得都处理了, 剩下的俺通知你了.反正调用是失败了.

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     vonNeumann (劣币驱逐良币) 于  (Tue Mar 18 14:31:59 2014)  提到:

    要求代码都写得 exception safe 也是一个很高的要求。工程上,规定返回值必须检查,比规定所有代码都要异常安全,执行起来容易得多。

    C++ 里没有原生的 finally 支持,所有需要清理的情况都要搞一个类来做 RAII 很麻烦。好在 C++11 可以山寨类似 finally 的功能。

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Tue Mar 18 14:34:36 2014)  提到:

    SCOPE_EXIT folly开源的,不需要自己轮。当然轮起来也很方便。

    【 在 vonNeumann (劣币驱逐良币) 的大作中提到: 】

    要求代码都写得 exception safe 也是一个很高的要求。工程上,规定返回值必须检查,比规定所有代码都要异常安全,执行起来容易得多。

    C++ 里没有原生的 finally 支持,所有需要清理的情况都要搞一个类来做 RAII 很麻烦。好在 C++11 可以山寨类似 finally 的功能。

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Tue Mar 18 14:53:17 2014)  提到:

    异常安全太难了

    另外,RAII很难避免析构函数抛异常

    【 在 vonNeumann (劣币驱逐良币) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     openyy (openyy) 于  (Tue Mar 18 15:16:30 2014)  提到:

    是否忽略是调用方决定的事,不是被调用方决定的事.

    你写下层函数的时候,怎么知道上层调用者是不是忽略?

    又怎么知道是该用错误码还是抛异常呢?

    上层函数调用下层3-5个函数,都有可能抛异常,难道不是不同的异常不同的处理么?

    错误码是分别处理。异常你写一遍什么意思?

    出错不处理,打点log, 最后程序崩掉。

    大try catch, 打点log, 最后程序结束。

    能有多大区别?那么深的层次,你能正确释放所有资源?

    异常强制上层云云,你只能强制自己,你能强制上层?

    还不是那句话,你不管你死屁了,反正我不管。

    检查错误码并作相应处理都嫌麻烦,能做到exception safe可能么?

    一个try/catch 然后忽略大部分异常,是通常做法吧。

    对于错误处理的覆盖,大概率低于用错误码的程序员。

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Tue Mar 18 15:27:10 2014)  提到:

    等debug的时候 你就哭吧

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Tue Mar 18 15:27:28 2014)  提到:

    finally里抛异常算什么...

    【 在 Tinro (老天若) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Tue Mar 18 15:34:39 2014)  提到:

    不知道啊,c++没有finally

    我一直觉得c++的异常安全就是摆设。既要通过构造析构管理资源,又不让析构函数抛异常(或者析构函数抛异常就破坏异常安全),这不是自己打自己脸么

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Tue Mar 18 15:39:42 2014)  提到:

    错误码一旦需要debug,你得在所有错误处理的地方打印错误信息,你才能知道到底是哪里出了问题。exception就方便了,只要你把最上面的try-catch注释掉,程序崩溃了就能打stack trace,如果用-g -ggdb编译,你可以立刻知道是哪行抛的异常。比error code方便无数倍。

    我会告诉你glog这个利器么?

    【 在 BrightLiang (WenQiang Xu@米国) 的大作中提到: 】

    等debug的时候 你就哭吧

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Tue Mar 18 16:39:36 2014)  提到:

    异常的逻辑是:出了错必须处理,你想吞掉错误不让上面知道,那就就得很麻烦地写一个try-catch把它吃掉。

    错误码的逻辑是:出了错默认不处理。你要处理错误,就得很麻烦地一种情况一种情况处理。

    人都是懒的,所以这就是为什么我说的,一个大的软件公司,招的是很好的码农,codebase里都有95%以上的需要检查返回值的错误码的地方没有被处理。

    异常和错误码的孰优孰劣一目了然。

    所以你说的“是否忽略是调用方决定的事,不是被调用方决定的事.”,本身并没有错,是的,它提供给程序员更多的flexibility,去做想做的事情:也就是忽略掉这个错误,让程序在已经出错的情况下继续执行。但是,这种灵活性带来的代价就是代码质量非常差,非常难以维护。话说异常处理也可以吞掉这个异常,只是你更麻烦而已。你需要explicitly地吞掉这个异常。还是那句话,孰优孰劣一目了然。

    “上层函数调用下层3-5个函数,都有可能抛异常,难道不是不同的异常不同的处理么?

    错误码是分别处理。异常你写一遍什么意思?”

    异常也可以分别处理的,你3-5个函数也可以分别try-catch,并不比你分别if-else多写几行代码。但是异常处理又提供了灵活性,你可以在你觉得合适的地方去处理异常。唯一不能做的是忽略掉这个异常。

    “出错不处理,打点log, 最后程序崩掉。

    大try catch, 打点log, 最后程序结束。

    能有多大区别?那么深的层次,你能正确释放所有资源?”

    我觉得你这个地方非常地自相矛盾。“出错不处理”,我指的是你不检查返回值,你说的是检查返回值,但是不返回给上层,而是直接crash掉。我说的现实是,大多数情况下,人们连crash掉都不会做,因为他们根本不记得检查这个返回值。

    “检查错误码并作相应处理都嫌麻烦,能做到exception safe可能么?”exception safe取决于你做到哪个层次。我个人认为,通常的系统里面,只要保证resource不泄露就可以了。更高级别的exception safe是不必要的。而做到这个就不是很难,只要keep in mind,用smart pointer,用STL 容器,不用裸指针,用SCOPE_EXIT去写finally的code。可以说就是一个习惯问题。而且代码的行数几乎不变,反而有可能减少。

    比如:

    T* t = new T;

    // blabla

    delete t;

    unique_ptr<T> t(new T);

    // blablabla

    还有

    File f = File.open("1.txt");

    if (!f.isOpen())) {

    return false;

    }

    if (!doSomething()) {

    f.close();

    reutrn false;

    }

    if (!doSomething2()) {

    f.close();

    return false;

    }

    File f = File.open("1.txt");

    SCOPE_EXIT { f.close(); };

    doSomething();

    doSomething2();

    哪个更麻烦写?人都是懒的,哪种风格更容易推行?还是那句话,孰优孰劣一目了然。

    “一个try/catch 然后忽略大部分异常,是通常做法吧。

    对于错误处理的覆盖,大概率低于用错误码的程序员。”

    这取决于程序的逻辑。如果错误是那种轻微的可以恢复的,首先未必需要用异常;其次,就是用异常,也可以在下层去try-catch然后恢复执行。异常可以轻松实现和错误码相同的逻辑。但是又能很轻松地实现一些错误码难以实现的逻辑,比如在上层try-catch。

    还有,现实就是,返回值的错误码有极大概率不被检查。同样是不检查,异常至少能防止带错运行,错误码就只能呵呵呵呵了。

    【 在 openyy (openyy) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     fonair (fonair) 于  (Tue Mar 18 16:42:29 2014)  提到:

    C++异常自然有其合理性,粗心的程序员完全可以不检查error code直接往下执行,这样问题可能发生在离发生很远的地方;异常本身是好东西,只是不要滥用即可

    【 在 Tinro (老天若) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     PGP (---) 于  (Tue Mar 18 18:08:51 2014)  提到:

    先把需要让程序崩掉的情况排除,这是bug,不是exception。

    不需要处理的错误也排除,这种时候最多打个log。

    错误码和异常的作用就是告诉调用者出了个需要处理的错误和大概的出错原因。就这个目的而言,错误码的工作方式没有任何优势。低效,这个一堆的if else就看的出来;携带信息有限,一般就是搞一个巨大的enum,然后调用者还需要去搞什么getEnumString。这个巨大的enum表格还是高度概括的信息。而用异常你可以在现场组织任何信息并保证这个信息能传到上面;最重要的一点是用错误码就必须在不需要处理错误的层次处理错误,仅仅为了把错误传上去,一个错误要重复处理无数次,不就是人工模拟jump或exception吗?跟在c++里到处用new delete的行为有什么区别?

    【 在 openyy (openyy) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Tue Mar 18 19:14:35 2014)  提到:

    最后展开一下PGP所说的低效问题。就是错误码if-else这种错误处理方式的性能也不好,而且为了传递给上层,同错误处理无关的调用层次上也又要承受if-else的overhead。而且即使不发生错误,程序正常执行的情况下,也照样要承受相应的overhead。

    至于exception,现在的C++ compiler早就已经可以做到在不发生异常的时候没有overhead;相反,错误码即使在正常情况下还要执行if-else。

    exception的一点overhead是阻止了编译器的进行code-movement的优化。但是只要被调用的函数不是在同一个CU里面,那这个优化是否能进行和调用函数是否真的会抛出异常无关,因为C++本来就默认是任何函数都可以抛出异常的,除非你非常蛋疼地给所有的函数都加上nothrow。

    同时随处可见的if-else也会造成control flow难以分析,导致编译器的优化能力下降。所以即使你加了nothrow,未必能比exception生成更高效的代码。

    也许有人要说,这点性能差别可以忽略。确实,我也从始至终没有强调这个,因为exception在维护上的,调试上的,可读性上都胜过错误码,我加上这一条只是为了说明excption完胜错误码而已。

    【 在 PGP (---) 的大作中提到: 】

    先把需要让程序崩掉的情况排除,这是bug,不是exception。

    不需要处理的错误也排除,这种时候最多打个log。

    错误码和异常的作用就是告诉调用者出了个需要处理的错误和大概的出错原因。就这个目的而言,错误码的工作方式没有任何优势。低效,这个一堆的if else就看的出来;携带信息有限,一般就是搞一个巨大的enum,然后调用者还需要去搞什么getEnumString。这个巨大的enum表格还是高度概括的信息。而用异常你可以在现场组织任何信息并保证这个信息能传到上面;最重要的一点是用错误码就必须在不需要处理错误的层次处理错误,仅仅为了把错误传上去,一个错误要重复处理无数次,不就是人工模拟jump或exception吗?跟在c++里到处用new delete的行为有什么区别?

    【 在 openyy (openyy) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     piggestbaby (吃的胖胖的(~~**~~)) 于  (Tue Mar 18 19:48:11 2014)  提到:

    总体来说,性能关键的地方使用错误码避免用异常

    错误检查频繁的地方用异常

    在关键的 api 设计上, 可能需要同时两套 api

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     fanci (大葡萄) 于  (Tue Mar 18 20:22:14 2014)  提到:

    异常就是为了快糙猛

    【 在 BrightLiang () 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Tue Mar 18 22:09:05 2014)  提到:

    那些有finally的语言,Java,C#,可以在finally里抛异常吗?

    【 在 Tinro (老天若) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Tue Mar 18 22:11:37 2014)  提到:

    你这回帖...感觉likankyo那洋洋洒洒一堆你都没看就回了...异常显然比用错误码有性

    能优势啊...

    【 在 piggestbaby (吃的胖胖的(~~**~~)) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     iamape (iamape) 于  (Tue Mar 18 22:16:57 2014)  提到:

    异常需要记录局部对象好在异常抛出时作destructor,看不出来异常哪里有性能优势了

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Tue Mar 18 22:28:52 2014)  提到:

    你再想想?

    【 在 iamape (iamape) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     qblyy (找美国程序员工作) 于  (Wed Mar 19 01:55:48 2014)  提到:

    Java可以

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Wed Mar 19 07:45:16 2014)  提到:

    那Java里,在finally里抛了异常以后,抛出异常的语句后面那些释放资源的代码还会被

    调用吗?

    【 在 qblyy (找美国程序员工作) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     qblyy (找美国程序员工作) 于  (Wed Mar 19 08:07:17 2014)  提到:

    http://www.hpenterprisesecurity.com/vulncat/en/vulncat/java/poor_error_handling_throw_inside_finally.html

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     piggestbaby (吃的胖胖的(~~**~~)) 于  (Wed Mar 19 08:36:05 2014)  提到:

    异常和错误码如果实现完全一样的功能, 错误码的性能要更高

    主要与异常的实现机制有关系

    这个业界早有公论了

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     piggestbaby (吃的胖胖的(~~**~~)) 于  (Wed Mar 19 08:54:46 2014)  提到:

    举个例子来说, 我要做一个判断字符串是否是数字的函数

    有两种方案用返回值来标识:

    第一种:

    bool isNumber(string s)

    第二种

    void parseNumber(string s) throw ParseForamtException

    如果对成千上万个字符串来迭代执行的话, 效率的差别是巨大的。

    很不幸的是, .net 类库里面就出现了第二种这种设计

    因此,异常在绝大部分情况下要优于错误码是没有异议的

    但是错误码也是有其存在价值的, 不能滥用异常, 完全取代错误码。

    我认为目前将异常的设计和使用限制在文件 IO, 网络 IO, 数据库访问的范围内应该已

    经满足绝大部分需求了。

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Wed Mar 19 08:54:47 2014)  提到:

    如果涉及到计算  触发异常可能是算法问题 而不是程序逻辑问题  你看那些stack trace p用没有

    有些库搞的异常简直是脑残  比如 矩阵求逆  输入有问题 maltab做法是输出空矩阵 有问题可以画图

    如果这个也抛异常 算法没法调试

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Wed Mar 19 09:07:29 2014)  提到:

    所以这种做法和在析构函数里抛异常有什么本质区别呢?你再回去看看你回我的那个帖

    子,看看我回的Tinro那篇帖子。

    【 在 qblyy (找美国程序员工作) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Wed Mar 19 09:08:01 2014)  提到:

    这个公论的问题就在于 早,太早了,早 就不是这样了

    我真诚的建议你再认真读一遍likankyo那篇帖子

    【 在 piggestbaby (吃的胖胖的(~~**~~)) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     piggestbaby (吃的胖胖的(~~**~~)) 于  (Wed Mar 19 09:13:24 2014)  提到:

    很多年前就在说这个了

    问题就在于这个在不发生异常的情况下,性能没损失

    这种情况,只能用于错误不可恢复的情况

    问题是很多情况下错误是可以恢复的

    很多情况下, 非要用异常代替返回值, 就会引发频繁的异常

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     PGP (---) 于  (Wed Mar 19 09:14:32 2014)  提到:

    大概算一下,假设不查错程序运行时间是1,用了异常在正常流程下程序运行时间是1,异常发生的情况下运行时间夸张一点1.15吧,用错误码不管什么流程运行时间是1.01,假设异常发生的概率是千分之一,统计上运行一千次用异常的代码期待运行时间是1000.15, 而用错误码的代码期待运行时间是1010,高下立判

    【 在 piggestbaby (吃的胖胖的(~~**~~)) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     piggestbaby (吃的胖胖的(~~**~~)) 于  (Wed Mar 19 09:16:34 2014)  提到:

    -___-!!!

    【 在 PGP (---) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Wed Mar 19 09:18:40 2014)  提到:

    呃,你这段话体现了对异常的最普遍的一种误解——即“异常是用于流程控制的”

    【 在 piggestbaby (吃的胖胖的(~~**~~)) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     beatrice (bx) 于  (Wed Mar 19 09:25:39 2014)  提到:

    我觉得“异常是用于异常流程控制的”应该没说错……

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     qblyy (找美国程序员工作) 于  (Wed Mar 19 09:32:30 2014)  提到:

    Int32.TryParse Method (String, Int32)

    .NET Framework 4.5 Other Versions 21 out of 30 rated this helpful - Rate this topic

    Converts the string representation of a number to its 32-bit signed integer equivalent. A return value indicates whether the conversion succeeded.

    Namespace:  System

    Assembly:  mscorlib (in mscorlib.dll)

    【 在 piggestbaby (吃的胖胖的(~~**~~)) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     piggestbaby (吃的胖胖的(~~**~~)) 于  (Wed Mar 19 09:40:02 2014)  提到:

    找的不错, 对于同一个 api

    提供了两种设计

    使用错误码 和 使用异常同时出现是可能的

    根据需要和性能使用更合适的

    【 在 qblyy (找美国程序员工作) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Wed Mar 19 10:12:14 2014)  提到:

    允许,而且会break finally,这也是我认为异常的一个劣势,一个流程中只能有一个异常

    明确站个队吧,我认为C++异常是一个非常糟糕的设计,它只解决了一个问题,就是对于已经定义了返回值类型的函数,可以多一种返回的方式(比如构造函数、操作符重载就不得不用异常,dynamic_cast也不得不用异常,其他的例子类似)。就标准库中的实践来看,也仅仅是在不得不用的时候才用异常机制。我认为合理的用法是,尽量避免在以上情形中使用异常,让构造、析构、操作符都成为非常轻量级的运算。对可能产生异常的操作用合理的api设计来实现;对繁琐的错误码检查用合理的代码结构设计来避免。同时基于此,我认为用RAII管理外部资源也不是一个好的设计。我的建议是手动释放外部资源,RAII最多只用于调用轻量级的析构函数和释放内存。如果函数出口太多,那么就重构。

    对了,你会发现这种写法很像C。实际上我们能招聘到的90%以上的C++程序员,对C++的使用都仅限于C加上class,这也是最现实、最实际的用法。在现实环境中能够让代码有更好的可维护性。

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Wed Mar 19 11:57:28 2014)  提到:

    什么是“异常流程”

    【 在 beatrice (bx) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Wed Mar 19 12:05:11 2014)  提到:

    我对此观点唯一的疑虑是这所谓的能招到的90%以上的C++程序员是否有足够的自觉和能

    力去重构。

    【 在 Tinro (老天若) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Wed Mar 19 13:20:59 2014)  提到:

    我见到不重构把代码copy很多次的,只要不嫌乱,能保证释放,也就将就用了...

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Wed Mar 19 16:01:13 2014)  提到:

    “一个流程中只能有一个异常”,你用错误码就能返回多个错误码了么?

    “它只解决了一个问题,就是对于已经定义了返回值类型的函数,可以多一种返回的方式”。我列举的那么多错误码的糟糕之处都被选择性无视了啊?

    重复下面的话十遍:“错误码允许被忽略,导致系统带错运行,系统不稳定;允许系统带错执行,导致出错位置和真正原因发生地点相距甚远,导致调试困难;错误码导致正常情况的执行逻辑和错误处理的逻辑混杂在一起,降低可读性;错误码携带信息有限;错误码在和错误无关的调用层次上也要检查错误码,导致代码大量冗余;错误码在正常执行的时候也会因为检查错误码造成性能损失”

    再重复下面的话十遍:“异常不允许被忽略,避免系统带错执行;异常发生的时候就是出错的位置,可以有stack trace,错误定位迅速,调试方便;错误吗正常情况的执行逻辑和错误处理的逻辑分开,极大提高代码清晰度和可读性;异常可以携带任意量的信息,方便调试;异常自动向上传递,在无关的调用层次上不需要额外代码,代码简洁清晰;异常在正常执行的时候完全没有性能损失,编译器方便优化”

    你的根本前提都错了,下面的那些论点我就不需要说什么了。

    “实际上我们能招聘到的90%以上的C++程序员,对C++的使用都仅限于C加上class”,对于这种素质的人,我觉得就不应该让他们碰底层的代码。让他们写ruby on rails去吧。如果你们只能找到这种人,就得反思一下公司的招人和筛选的方法了。

    【 在 Tinro (老天若) 的大作中提到: 】

    允许,而且会break finally,这也是我认为异常的一个劣势,一个流程中只能有一个异常

    明确站个队吧,我认为C++异常是一个非常糟糕的设计,它只解决了一个问题,就是对于已经定义了返回值类型的函数,可以多一种返回的方式(比如构造函数、操作符重载就不得不用异常,dynamic_cast也不得不用异常,其他的例子类似)。就标准库中的实践来看,也仅仅是在不得不用的时候才用异常机制。我认为合理的用法是,尽量避免在以上情形中使用异常,让构造、析构、操作符都成为非常轻量级的运算。对可能产生异常的操作用合理的api设计来实现;对繁琐的错误码检查用合理的代码结构设计来避免。同时基于此,我认为用RAII管理外部资源也不是一个好的设计。我的建议是手动释放外部资源,RAII最多只用于调用轻量级的析构函数和释放内存。如果函数出口太多,那么就重构。

    对了,你会发现这种写法很像C。实际上我们能招聘到的90%以上的C++程序员,对C++的使用都仅限于C加上class,这也是最现实、最实际的用法。在现实环境中能够让代码有更好的可维护性。

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Wed Mar 19 16:40:49 2014)  提到:

    所以所有的讨论关键点在于前提

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Wed Mar 19 16:49:17 2014)  提到:

    贴一下我关于错误码和异常的性能比较。我的程序里面,在正常的流程下,使用异常比使用错误码快26%;在发生异常的流程下,异常比错误码慢300倍。当然不同的CPU上结果可能会不一样。我在我一个虚拟机里就没有差到26%这么多。

    原因很简单,循环部分,最后生成的代码里面,使用异常的函数里生成的机器码是这样的:

    401770:       48 8d 74 24 20          lea    0x20(%rsp),%rsi

    401775:       0f b6 fb                movzbl %bl,%edi

    401778:       e8 53 07 00 00          callq  401ed0 <_Z14incrementThrowiPi>

    40177d:       83 c3 01                add    $0x1,%ebx

    401780:       44 39 e3                cmp    %r12d,%ebx

    401783:       75 eb                   jne    401770 <_Z17benchmarkTryCatchbi+0xa0>

    使用错误码的函数里生成的机器码是这样的:

    401330:       83 f8 32                cmp    $0x32,%eax

    401333:       0f 84 3f 02 00 00       je     401578 <_Z15benchmarkIfElsebi+0x2e8>

    401339:       83 f8 64                cmp    $0x64,%eax

    40133c:       0f 1f 40 00             nopl   0x0(%rax)

    401340:       0f 84 5a 02 00 00       je     4015a0 <_Z15benchmarkIfElsebi+0x310>

    401346:       3d ff 00 00 00          cmp    $0xff,%eax

    40134b:       0f 94 c0                sete   %al

    40134e:       0f b6 c0                movzbl %al,%eax

    401351:       41 01 c5                add    %eax,%r13d

    401354:       83 c3 01                add    $0x1,%ebx

    401357:       44 39 e3                cmp    %r12d,%ebx

    40135a:       74 24                   je     401380 <_Z15benchmarkIfElsebi+0xf0>

    40135c:       48 8d 74 24 20          lea    0x20(%rsp),%rsi

    401361:       0f b6 fb                movzbl %bl,%edi

    401364:       e8 27 0b 00 00          callq  401e90 <_Z15incrementIfElseiPi>

    401369:       83 f8 0a                cmp    $0xa,%eax

    40136c:       75 c2                   jne    401330 <_Z15benchmarkIfElsebi+0xa0>

    40136e:       83 c3 01                add    $0x1,%ebx

    401371:       41 83 c6 01             add    $0x1,%r14d

    401375:       44 39 e3                cmp    %r12d,%ebx

    401378:       75 e2                   jne    40135c <_Z15benchmarkIfElsebi+0xcc>

    40137a:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

    可以看的出来,使用异常的代码,生成的机器码极为精简高效,和没有try-catch生成的代码一样。所以再一次验证了try-catch block里面,只要没有抛出异常,就没有性能损失。

    结论:

    1)不要把异常作为flow control来使用,一旦发生异常,C++的处理速度是比较慢的,大约是微秒级的;

    2)因为仅仅是微秒级的,所以只要不是作为flow control频繁发生,而是在真正出问题的地方抛出,这点性能损失可以忽略。比如IO错误,网络超时等等,所造成的延迟比微秒级别高出太多;

    3)在正常的逻辑流程下,不抛出异常的情况下,异常处理没有任何性能损失。而错误码导致编译器生成大量代码检查错误码,形成很大的性能损失。考虑到这里的benchmark只是一处错误码在一层调用上的性能损失。如果每一个地方都要检查错误码,每一层上又要检查和传递向上错误码,性能损失就很可观了。

    总结:

    异常处理在不发生异常的情况下没有任何代价。而错误码即使在正常流程都需要付出代价。所以,只要做到不滥用异常,用异常来做flow control,那么从性能上讲异常是比错误码更好的选择。

    【 在 PGP (---) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Wed Mar 19 16:57:18 2014)  提到:

    所以说啊,我列举的这么多条理由都直接反驳了你的“它只解决了一个问题”的前提,所以你说的“异常处理是个糟糕的设计”也就站不住脚了。

    错误码作为上古时代,人们茹毛饮血的产物,放到现在有太多问题遭人诟病。异常很大程度上解决了这些问题,虽然也或多或少引入了一些新的问题。正如现代人的生活方式虽然也存在问题,虽然有地沟油和雾霾,但是没有人愿意回到原始社会过着没有电脑没有网络没有iPhone的生活了。

    【 在 Tinro (老天若) 的大作中提到: 】

    所以所有的讨论关键点在于前提

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Wed Mar 19 17:24:49 2014)  提到:

    好吧,我换句话说,异常是个非常优秀的设计,但需要有人懂得用它

    希望能结束这样无谓的争论。

    你的分析都很好,我非常支持。

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Wed Mar 19 18:07:06 2014)  提到:

    我并不认为异常是个“非常”优秀的设计,只不过它是个完胜错误码的设计。

    将来或许会有比异常更好的设计出现。

    异常有它的问题,但是要回到错误码是不对的。

    仅此而已。

    【 在 Tinro (老天若) 的大作中提到: 】

    好吧,我换句话说,异常是个非常优秀的设计,但需要有人懂得用它

    希望能结束这样无谓的争论。

    你的分析都很好,我非常支持。

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     hefengrren (AX) 于  (Wed Mar 19 21:52:34 2014)  提到:

    分情况。用过力矩扳手,就不用普通扳手了?

    错误码:简单易懂,心理负担小。就是代码行数可能多点。

    异常:看似简单,心理负担?没法说

    拉上大神:

    http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/352949.aspx

    http://www.yosefk.com/blog/error-codes-vs-exceptions-critical-code-vs-typical-code.html

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Schlafgern (婆婆大的) 于  (Wed Mar 19 22:02:15 2014)  提到:

    对于异常和错误码比较,我记得有这么一句话,好像是error handling is evil, 反正意思就是错误处理本来就是一件很脏的活,很多时候我们诟病异常不好,写起来不爽,团队不好执行,可是仔细想想,其实异常目前看已经算一个不错的错误处理的方案了,其他的方式,比如错误码(全局的或者返回的),你想让你的团队保证检查错误更不可能,而且代码看起来特别冗余,本来逻辑上很简单的代码要多写很多行

    另外关于错误码和异常性能的比较,可能还有另外一点因素,就是异常处理需要rtti的支持,这个rtti的支持需要额外的性能开销,而有些项目使用c++就是多了class(包括virtual method)的c,或者因为跨平台的因素,而没有打开rtti支持(就我知道好像qnx,还有wince的老编译器不支持rtti),这时候考虑异常就把rtti的开销也算进去了

    【 在 likanKyo 的大作中提到: 】

    ☆─────────────────────────────────────☆

     fonair (fonair) 于  (Wed Mar 19 22:21:09 2014)  提到:

    这个问题More Effective C++讲的清清楚楚,这里这么多人搞C++的,居然没人抬出这

    本神作!

    【 在 Schlafgern (婆婆大的) 的大作中提到: 】

    就是错误处理本来就是一件很脏的活,很多时候我们诟病异常不好,写起来不爽,团队不

    好执行,可是仔细想想,其实异常目前看已经算一个不错的错误处理的方案了,其他的方

    式,比如错误码(全局的或者返回的),你想让你的团队保证检查错误更不可能,而且代

    码看起来特别冗余,本来逻辑上很简单的代码要多写很多行

    持,这个rtti的支持需要额外的性能开销,而有些项目使用c++就是多了class(包括virtual

    method)的c,或者因为跨平台的因素,而没有打开rtti支持(就我知道好像qnx,还有wince

    的老编译器不支持rtti),这时候考虑异常就把rtti的开销也算进去了

    ☆─────────────────────────────────────☆

     TheChild (慢步者) 于  (Wed Mar 19 22:57:59 2014)  提到:

    你举的示例代码没有说服力,两段代码功能不一样,你没把恶心的 try ... catch

    ... 写出来,不厚道了。

    第一段代码可以改成:

    bool f() {

    return doSomething()

    && doSomething2()

    && doSomething3();

    }

    bool g() {

    return f()

    && doSomething4();

    }

    有什么恶心?

    想说明问题,你得举更合适的例子。

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Wed Mar 19 22:59:19 2014)  提到:

    “异常处理需要rtti的支持”,求详细,谢谢

    【 在 Schlafgern (婆婆大的) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     TheChild (慢步者) 于  (Wed Mar 19 23:25:18 2014)  提到:

    写这段示例代码对于你的论点没有帮助,它们的功能不完全等同,你的 try ...

    catch ... 在哪里?

    不知写这样的代码算不算懒:

    File f = File.open("1.txt");

    if (!f.isOpen())) {

    return false;

    }

    return doSomething()

    && doSomething2();

    }

    或者:

    File f = File.open("1.txt");

    return f.isOpen()

    && doSomething()

    && doSomething2();

    }

    (假定 File 类析构时自动调用 close 方法,如果不是,就派生个会这么做的类来

    用)

    想让大家信服,你恐怕需要贴一些你写的最得意的使用异常的代码。

    【 在 likanKyo (考完了...) 的大作中提到: 】

    地写一个try-catch把它吃掉。

    种情况处理。

    农,codebase里都有95%以上的需要检查返回值的错误码的地方没有被处理。

    ☆─────────────────────────────────────☆

     PGP (---) 于  (Wed Mar 19 23:35:34 2014)  提到:

    你没看明白,他写的//blablabla是省略中间无数代码,不是注释。

    【 在 TheChild (慢步者) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     hefengrren (AX) 于  (Wed Mar 19 23:36:27 2014)  提到:

    C++11 很容易发现,默认挂掉:析构函数默认noexcept——只要没有显式声明抛异常,而直接或间接抛了异常,那么就意味着std::terminate。

    【 在 Tinro (老天若) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     TheChild (慢步者) 于  (Wed Mar 19 23:57:03 2014)  提到:

    想看看那无数代码是怎么写的

    【 在 PGP (---) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Schlafgern (婆婆大的) 于  (Thu Mar 20 00:00:59 2014)  提到:

    catch 异常的时候,总是要知道异常的实际runtime type(typeid这些),这个需要打开rtti支持,在visual studio是/GR选项我记得

    【 在 sunseraphic 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Thu Mar 20 00:18:45 2014)  提到:

    据我所知,虽然异常的实现是会要求类型信息,但是RTTI的支持不是同时需要的,否则

    关闭了RTTI的情况下异常怎么实现。

    至于要求具备类型信息的异常实现是否会导致你说的运行时性能开销倒是可以讨论——基

    于具体实现而言。

    【 在 Schlafgern (婆婆大的) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Schlafgern (婆婆大的) 于  (Thu Mar 20 01:01:33 2014)  提到:

    刚才仔细查了一下,确实rtti支持是不需要的,人云亦云了,听同事前阵子讨论是否在项目中支持exception的时候提了这个,我自己没具体查就信了-,-

    具体对象的类型信息检查的开销也还仅仅是在异常产生需要处理以后才会发生的,这个开销正常处理的时候是不需要的吧

    至于具体对象的类型信息应该是c++本来就必须支持的吧

    这个我还想具体问一句,好像rtti的额外开销挺大的,具体是dynamic_cast, typeinfo()之类的,为啥呢?这些信息难道不是对象信息里面必须携带的么?

    【 在 sunseraphic 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Thu Mar 20 01:11:29 2014)  提到:

    简单的说,C++不支持反射,所以一个用户自定义类型的对象一般是不带其自身类型信息

    的(当然内置类型就更不带了),但是对于面向对象编程,运行时的类型信息又是必要

    的,所以最低限度的,对于拥有虚函数的对象而言起码是有虚表的,更多的运行时类型

    信息一般也和虚表放在一起,当然有虚表的数据毕竟只是一部分,所以typeid这个运算

    符即有可能在编译期求值,也有可能在运行期求值,不论是typeid的运行期求值,dyna

    mic_cast还是一般的动态绑定(通过基类指针进行的虚函数调用),开销大致在一个数

    量级上,相比不需要运行时类型信息的计算,确实会大些,但是如果不是计算密集型的

    操作,也可以忽略之。

    回头说到异常处理实现中需要的类型信息,基本都是在实现抛出异常的底层数据结构里

    带有一个标明类型信息的结构,以供catch块检查是否需要捕捉,这个开销在没有发生异

    常的时候是不存在的。

    【 在 Schlafgern (婆婆大的) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Schlafgern (婆婆大的) 于  (Thu Mar 20 01:19:22 2014)  提到:

    也就是说rtti的开销复杂度其实就是虚标的开销复杂度,是么?

    仅仅就因为typeinfo()这个函数的要求编译器保存了更多的类型信息,但是有rtti的虚表在query上的开销和没有rtti是一样的,这么理解对吧 ?

    【 在 sunseraphic 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Schlafgern (婆婆大的) 于  (Thu Mar 20 01:24:06 2014)  提到:

    就我自己在工作中的感受,很多c++程序员因为以前大多是写c的,所以很饭C的那一套,很多用class就和struct一样,继承也仅仅是因为复用代码,OOP, s.o.l.i.d.那些东西很多都没有概念

    【 在 fonair 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Thu Mar 20 02:04:58 2014)  提到:

    虚(函数)机制本身属于RTTI的一部分...

    【 在 Schlafgern (婆婆大的) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Schlafgern (婆婆大的) 于  (Thu Mar 20 02:19:37 2014)  提到:

    我也这么认为的,但是为啥可以用virtual method,但是关闭rtti支持呢?应该说rtti有不同层次的支持吧

    【 在 sunseraphic 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Thu Mar 20 03:47:35 2014)  提到:

    你没注意到我有几处"//blablabla",我是想说那几处还有一些别的代码。所以你没法写成

    doSomething() && doSomething2() && doSomething3()

    这种形式。

    而且你说功能不一样?当然是一样的。功能就是把下面的错误向上传递。对于异常处理,这种情况下我本来就不需要try-catch。

    【 在 TheChild (慢步者) 的大作中提到: 】

    你举的示例代码没有说服力,两段代码功能不一样,你没把恶心的 try ... catch

    ... 写出来,不厚道了。

    第一段代码可以改成:

    bool f() {

    return doSomething()

    && doSomething2()

    && doSomething3();

    }

    bool g() {

    return f()

    && doSomething4();

    }

    有什么恶心?

    想说明问题,你得举更合适的例子。

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     likanKyo (考完了...) 于  (Thu Mar 20 03:48:14 2014)  提到:

    你说功能不一样?当然是一样的。功能就是把下面的错误向上传递。对于异常处理,这

    种情况下我本来就不需要try-catch,

    再说了,我这里也是省略了doSomething()和doSomething2()之间的“//blabla”,中间有些别的代码,你根本就没有办法写成doSomething() && doSomething2()的形式。

    多写点code就知道了,实际的production code里总是面临各种修改的需求,随着时间推进还需要加各种新的逻辑进来。在函数调用之间插别的逻辑很正常,想到处推广doSomething() && doSomething2() 这种写法根本就不现实。有任何修改的需求都会把你这个写法重写成我写的那个样子的。这个是现实,骚年。

    【 在 TheChild (慢步者) 的大作中提到: 】

    写这段示例代码对于你的论点没有帮助,它们的功能不完全等同,你的 try ...

    catch ... 在哪里?

    不知写这样的代码算不算懒:

    File f = File.open("1.txt");

    if (!f.isOpen())) {

    return false;

    }

    return doSomething()

    && doSomething2();

    }

    或者:

    File f = File.open("1.txt");

    return f.isOpen()

    && doSomething()

    && doSomething2();

    }

    (假定 File 类析构时自动调用 close 方法,如果不是,就派生个会这么做的类来

    用)

    想让大家信服,你恐怕需要贴一些你写的最得意的使用异常的代码。

    【 在 likanKyo (考完了...) 的大作中提到: 】

    地写一个try-catch把它吃掉。

    种情况处理。

    农,codebase里都有95%以上的需要检查返回值的错误码的地方没有被处理。

    ☆─────────────────────────────────────☆

     xiaoyuer (十年又十年又十年) 于  (Thu Mar 20 08:01:28 2014)  提到:

    你说的这种本质还是C程序员呀,哈哈

    【 在 Tinro (老天若) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     dami2013 (大米) 于  (Thu Mar 20 08:21:13 2014)  提到:

    很多人这样,你干嘛不这样

    【 在 Schlafgern 的大作中提到: 】

    ☆─────────────────────────────────────☆

     cpper (cpp beginner) 于  (Thu Mar 20 09:00:09 2014)  提到:

    c++的异常悲催在从接口看不出有没有异常会抛出来

    【 在 likanKyo (考完了...) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Thu Mar 20 09:00:54 2014)  提到:

    关闭的是dynamic_cast,运行时typeid这些吧,虚机制基本上是大多数本质上差不多是

    C程序员的选择C++的原因,关了还不如直接写C去算了...

    【 在 Schlafgern (婆婆大的) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Thu Mar 20 09:03:59 2014)  提到:

    哪种语言的接口声明里包含了方法的异常规格?

    【 在 cpper (cpp beginner) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Thu Mar 20 09:07:11 2014)  提到:

    运行时的 有毛用..

    【 在 hefengrren (AX) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Thu Mar 20 09:19:46 2014)  提到:

    事实上能招聘到的很多都是C程序员

    优秀的C++程序员基本都去Google了,招一些底子还不错,凑合用,听话又好干活的程序员是绝大多数公司的现状,也是最现实、最经济的选择

    后果无非就是代码没那么现代化,像是上个世纪的,who cares。

    【 在 xiaoyuer (十年又十年又十年) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     cybereagle (2/3的沉默@XMUCSD) 于  (Thu Mar 20 09:29:05 2014)  提到:

    java就有啊

    public interface Closeable {

    public void close() throws IOException;

    }

    但是即便是Java这么啰嗦的语言也还是有RuntimeException可以不经声明直接抛出

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     qblyy (找美国程序员工作) 于  (Thu Mar 20 09:45:09 2014)  提到:

    貌似只有Java

    【 在 cybereagle (2/3的沉默@XMUCSD) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Thu Mar 20 09:56:41 2014)  提到:

    我记得你现在是Dieken的同事吧?

    【 在 Tinro (老天若) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Thu Mar 20 10:28:19 2014)  提到:

    嘿,看ip还真是。。

    但我现在写java。。。

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     xshoushoux (xshoushoux) 于  (Thu Mar 20 11:01:33 2014)  提到:

    囧。。。09年拿过你们家offer。。。当时和郑皓谈的。。。

    那时候george chu还是我的顶头上司。。。结果他现在倒是去了你们那儿。。。

    【 在 Tinro (老天若) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Tinro (老天若) 于  (Thu Mar 20 11:02:33 2014)  提到:

    -_-|||

    世界好小

    【 在 xshoushoux (xshoushoux) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     fonair (fonair) 于  (Thu Mar 20 12:59:21 2014)  提到:

    google社招变态不,我想一年之内试试

    【 在 Tinro (老天若) 的大作中提到: 】

    序员是绝大多数公司的现状,也是最现实、最经济的选择

    ☆─────────────────────────────────────☆

     cpper (cpp beginner) 于  (Thu Mar 20 17:01:53 2014)  提到:

    java好像有

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     fonair (fonair) 于  (Thu Mar 20 17:34:22 2014)  提到:

    C++也有

    void func() throw ();

    【 在 cpper (cpp beginner) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     Elric (钻石恒久远,一颗永留传) 于  (Thu Mar 20 17:47:11 2014)  提到:

    有一个疑问:

    如下函数

    int DownloadAndProcess(url)

    {

    int err = Download(url, file); //下载文件到磁盘

    // err可能值: ERR_NETWORKING, ERR_URL_NOT_FOUND, ERR_FILE_ACCESS ....

    //此处如果err有错, 返回什么? 返回自定义的错误码, 还是Download的错误码?

    int err2 = Process(file); //业务逻辑处理

    // err2可能值: ERR_FILE_ACCESS, ERR_FILE_FORMAT, ERR_FILE_TOO_LARGE ...

    // 此处如果err2有错, 返回什么? 返回自定义的错误码, 还是Process的错误码?

    }

    1.如果返回Download或者Process的错误码, 那么如果两种错误码有冲突怎么办?上层函数是不是要检查Download或Process所有的错误码?这样越到上层,要检查的错误码是不是越来越多?

    2.如果返回自定义错误码, 那么每个函数是不是都必须自己定义一套错误码?如何保证所有的这些错误码不冲突?

    假设DownloadAndProcess()自定义2个错误码: ERR_DOWNLOAD, ERR_PROCESS,那么上层函数是不是无法知道具体原因? 是ERR_URL_NOT_FOUND, ERR_FILE_ACCESS还是其他什么原因?

    【 在 BrightLiang (WenQiang Xu@米国) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     fonair (fonair) 于  (Thu Mar 20 18:08:11 2014)  提到:

    错误码是约定,你如果调用别人的函数返回的,翻译成自己的,当然如果和你们自己系统

    理的一样是最好了

    【 在 Elric (钻石恒久远,一颗永留传) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     kassu (nothing) 于  (Thu Mar 20 18:08:26 2014)  提到:

    std::error_code & std::error_condtion

    【 在 Elric (钻石恒久远,一颗永留传) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     xiaoyuer (十年又十年又十年) 于  (Thu Mar 20 19:47:37 2014)  提到:

    功能至上~,大部分工作就是码工呀, 搭好框架,各个吗工去填砖呗

    【 在 Tinro (老天若) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     redbird314 (苦逼100年啊100年) 于  (Fri Mar 21 05:01:12 2014)  提到:

    构造函数咋整?

    【 在 BrightLiang 的大作中提到: 】

    ☆─────────────────────────────────────☆

     TheChild (慢步者) 于  (Fri Mar 21 11:02:58 2014)  提到:

    你这么说是很不负责的。

    一段会抛异常的代码,没有处理异常,怎么能说跟一段不抛异常的代码功能一样呢?

    严谨,是对程序的基本要求之一,从这个例子看,你做得不严谨。

    “//blabla”是什么?你需要完整的贴出来。通过调整结构,代码可以在可读性、可扩

    展性上改善,并不一定需要用上某种技术(例如你推崇的异常)。

    另外问一句,你多大年纪了?

    【 在 likanKyo (考完了...) 的大作中提到: 】

    中间有些别的代码,你根本就没有办法写成doSomething() && doSomething2()的形

    式。

    ☆─────────────────────────────────────☆

     TheChild (慢步者) 于  (Fri Mar 21 11:13:49 2014)  提到:

    int DownloadAndProcess(url) 函数需要定义自己的错误码。

    如果你很懒,或者没有分辨详细错误信息的必要,可以只定义失败和成功的错误码,例

    如 0 表示成功,-1 表示失败。

    相对独立的工具类函数,可以独自定义各自的错误码,各函数有数值相同、意义不同的

    错误码也没关系。

    完整的库、与业务相关的函数,最好是从全局考虑,为各个函数定义数值不同的错误

    码。

    【 在 Elric (钻石恒久远,一颗永留传) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     TheChild (慢步者) 于  (Fri Mar 21 11:36:55 2014)  提到:

    如果对象在构造时发生了错误,可以把错误信息存储在类成员变量中,通过公有函数对

    外提供错误信息。

    或者把会发生错误的代码,从构造函数移出,封装成有返回值的初始化函数。

    这样做对于类的使用者来说,会增加少量代码(构造对象,然后检查错误信息或调用初

    始化函数),这样的代码增量不算大。

    【 在 redbird314 (苦逼100年啊100年) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     redbird314 (苦逼100年啊100年) 于  (Fri Mar 21 12:00:37 2014)  提到:

    不是吧。

    如果是的话,为什么mfc,wxwidget等等比较早期诞生的用cpp写的库都有实现自己的rtti。而虚函数机制显然都是用的语言的机制

    【 在 sunseraphic 的大作中提到: 】

    ☆─────────────────────────────────────☆

     redbird314 (苦逼100年啊100年) 于  (Fri Mar 21 12:02:36 2014)  提到:

    这样做显然有脱了裤子放屁的感觉

    【 在 TheChild 的大作中提到: 】

    ☆─────────────────────────────────────☆

     PGP (---) 于  (Fri Mar 21 12:20:20 2014)  提到:

    除了你说的增加代码还有别的好处吗?贵公司是按行算钱?

    【 在 TheChild (慢步者) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     PGP (---) 于  (Fri Mar 21 12:24:45 2014)  提到:

    有时候0是成功,有时候true是成功,有时候exe_ok是成功,有时候no_error是成功,你是不是每写一行都要去看看文档?

    【 在 TheChild (慢步者) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     worklife (work & life) 于  (Fri Mar 21 13:36:39 2014)  提到:

    构造都没成功,还能用类成员变量?

    【 在 TheChild (慢步者) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     TheChild (慢步者) 于  (Fri Mar 21 18:11:44 2014)  提到:

    直接好处是创建对象时不用捕捉异常

    【 在 PGP (---) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     TheChild (慢步者) 于  (Fri Mar 21 18:19:48 2014)  提到:

    调用每个不熟知的函数之前,肯定要查看函数说明(文档或声明),这是基本要求。

    【 在 PGP (---) 的大作中提到: 】

    功,你是不是每写一行都要去看看文档?

    ☆─────────────────────────────────────☆

     TheChild (慢步者) 于  (Fri Mar 21 18:26:58 2014)  提到:

    对象在构造时发生了错误,对象的属性可能不是正常的值,这不表示对象没有被创建。

    【 在 worklife (work & life) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     redbird314 (苦逼100年啊100年) 于  (Fri Mar 21 18:38:37 2014)  提到:

    他的意思是构造函数永远成功执行,哪怕内存分配不够,io错误,但通过一个叫错误码的成员变量来记录

    【 在 worklife 的大作中提到: 】

    ☆─────────────────────────────────────☆

     PGP (---) 于  (Fri Mar 21 18:48:39 2014)  提到:

    这算好处?。。。你不是还要检查错误码吗?

    【 在 TheChild (慢步者) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     worklife (work & life) 于  (Fri Mar 21 23:48:59 2014)  提到:

    阁下对c++的理解真是让人无语

    你继续吧

    【 在 TheChild (慢步者) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Sat Mar 22 15:30:15 2014)  提到:

    这种应该用状态流程图对业务流程进行设计 而不是依赖异常

    如果我做  一个错误报告就会生成 写入当前状态控制器

    状态控制器可以做成一个全局变量object

    DownloadAndProcess 返回 bool值 就可以,要么完成了 要么处错了

    int DownloadAndProcess(url)

    {

    int err = Download(url, file); //下载文件到磁盘

    // err可能值: ERR_NETWORKING, ERR_URL_NOT_FOUND, ERR_FILE_ACCESS ....

    //此处如果err有错, 返回什么? 返回自定义的错误码, 还是Download的错误码?

    int err2 = Process(file); //业务逻辑处理

    // err2可能值: ERR_FILE_ACCESS, ERR_FILE_FORMAT, ERR_FILE_TOO_LARGE ...

    // 此处如果err2有错, 返回什么? 返回自定义的错误码, 还是Process的错误码?

    }

    【 在 Elric 的大作中提到: 】

    ☆─────────────────────────────────────☆

     BrightLiang (WenQiang Xu@米国) 于  (Sat Mar 22 15:36:20 2014)  提到:

    这个是很恶心的

    【 在 cpper 的大作中提到: 】

    ☆─────────────────────────────────────☆

     PGP (---) 于  (Sat Mar 22 17:15:43 2014)  提到:

    你这是强行把一堆没有关系的功能和一个状态控制器耦合起来,图啥呢?

    【 在 BrightLiang (WenQiang Xu@米国) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     winberg (洪福齐天) 于  (Sat Mar 22 22:47:38 2014)  提到:

    C++里要把异常用好太困难了

    boost里都一堆问题

    因此,对大部分c++程序员来说,最安全的方式,禁止使用异常

    【 在 BrightLiang (WenQiang Xu@米国) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sunseraphic (この世界がいつかは幻に変わると) 于  (Sun Mar 23 01:18:06 2014)  提到:

    不不不,最安全的方式是禁止使用C++

    【 在 winberg (洪福齐天) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     xiaoyuer (十年又十年又十年) 于  (Sun Mar 23 06:17:46 2014)  提到:

    最安全方法是不用电脑

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     winberg (洪福齐天) 于  (Sun Mar 23 14:08:20 2014)  提到:

    说得好,除非万不得已千万不要用C++

    【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    【 在 BrightLiang (WenQiang Xu@米国) 的大作中提到: 】

    : 直接用错误代码就行了 非要整个异常 把程序弄崩溃了

    : 所以你的名字叫牛逼,发明 C++ 异常的是傻逼,定义 <stdexcept> 里面那些异常

    : 的也是傻逼

    : 其实我也这么觉得。。。C++异常根本就是sb

    : 写很多是不好,不过不能被忽略的错误抛出异常也不是什么不好的事

    : 抛出异常破坏第一现场

    : C++异常应该用在那些无法返回错误码的地方,比如 operator[]()重载函数里,能用错误码表示的,尽量还是用C方式的错误码吧

    : 所以你的名字叫牛逼,发明 C++ 异常的是傻逼,定义 <stdexcept> 里面那些异常

    : 的也是傻逼

    : 我个人觉得从软件工程的角度而言返回错误码是一个不太好的设计。用起来繁琐不说,更严重的问题是允许调用者忽略错误码。一个很大的软件公司,招的都是很好的码农,有人对codebase做过统计,代码里面95%以上的需要检查的返回值的错误码都没有得到检查。

    : 比较好的方法就是使用expcetion,同时要求caller能够做到exception safe,比如用smart pointer,比如用RAII之类的。其实养成习惯之后,这些都很方便的。比如不用new和delete,而是用容器;比如new的指针用unique或者shared包起来,这样反而省了一行delete,何乐而不为呢?

    : C++异常应该用在那些无法返回错误码的地方,比如 operator[]()重载函数里,能用错误码表示的,尽量还是用C方式的错误码吧

    : ...................

    : 我个人觉得从软件工程的角度而言返回错误码是一个不太好的设计。用起来繁琐不说,更严重的问题是允许调用者忽略错误码。一个很大的软件公司,招的都是很好的码农,有人对codebase做过统计,代码里面95%以上的需要检查的返回值的错误码都没有得到检查。

    : 比较好的方法就是使用expcetion,同时要求caller能够做到exception safe,比如用smart pointer,比如用RAII之类的。其实养成习惯之后,这些都很方便的。比如不用new和delete,而是用容器;比如new的指针用unique或者shared包起来,这样反而省了一行delete,何乐而不为呢?

    : C++异常应该用在那些无法返回错误码的地方,比如 operator[]()重载函数里,能用错误码表示的,尽量还是用C方式的错误码吧

    : ...................

    : expcetion 直接到log 或者大喇叭报警  而不是把程序给非法操作了

    : 比如 用 throw xxx  就写成  ErrorLog << "tmd error!"

    : log并不能取代exception。除非LOG(FATAL) << ...,否则程序还是继续得到执行(如果caller没有检查返回值),导致错误继续积累下去。

    : 而log(fatal)强制crash并不总是是最好的解决方案。因为有的时候错误不是致命的。比如一个server,由于query其他service的时候timeout了所以handle不了这个request,这样的错误至少不是致命的,还可以handle别的request。一个clean的方法就是在这里throw在request handle

    : 还有人说C++的exception不能有stack trace的信息,这个也是不对的。我看过有人写过一个.so,具体细节我不太清楚了,大致上是重新实现了C++ exception handling的ABI, 让它包含stacktrace的信息。然后LD_PRELOAD加载这个so的程序就可以有stacktrace了。可惜的是我找不到�

    : ...................

    : 我个人觉得从软件工程的角度而言返回错误码是一个不太好的设计。用起来繁琐不说,更严重的问题是允许调用者忽略错误码。一个很大的软件公司,招的都是很好的码农,有人对codebase做过统计,代码里面95%以上的需要检查的返回值的错误码都没有得到检查。

    : 比较好的方法就是使用expcetion,同时要求caller能够做到exception safe,比如用smart pointer,比如用RAII之类的。其实养成习惯之后,这些都很方便的。比如不用new和delete,而是用容器;比如new的指针用unique或者shared包起来,这样反而省了一行delete,何乐而不为呢

    : C++异常应该用在那些无法返回错误码的地方,比如 operator[]()重载函数里,能用错误码表示的,尽量还是用C方式的错误码吧

    : ...................

    : log并不能取代exception。除非LOG(FATAL) << ...,否则程序还是继续得到执行(如果caller没有检查返回值),导致错误继续积累下去。

    : 而log(fatal)强制crash并不总是是最好的解决方案。因为有的时候错误不是致命的。比如一个server,由于query其他service的时候timeout了所以handle不了这个request,这样的错误至少不是致命的,还可以handle别的request。一个clean的方法就是在这里throw在request handle

    : 还有人说C++的exception不能有stack trace的信息,这个也是不对的。我看过有人写过一个.so,具体细节我不太清楚了,大致上是重新实现了C++ exception handling的ABI, 让它包含stacktrace的信息。然后LD_PRELOAD加载这个so的程序就可以有stacktrace了。可惜的是我找不到�

    : ...................

    : 我其实不太理解你所说的第一现场。

    : 如果是throw的地方,你完全可以把需要的信息log(error)出来再throw,或者如果catch的地方需要这些值,可以把需要的信息加到exception里面去。

    : 如果是caller的地方,你也可以catch然后log再rethrow。毕竟如果用错误码的话,你anyway也需要有一段代码log(error)这个所谓的第一现场的。所以exception的工作量并不比错误码大,好处是在一个很深的调用里面,在你不需要第一现场的层上,完全不需要有error handling的代

    : ...................

    : 我其实不太理解你所说的第一现场。

    : 如果是throw的地方,你完全可以把需要的信息log(error)出来再throw,或者如果catch的地方需要这些值,可以把需要的信息加到exception里面去。

    : 如果是caller的地方,你也可以catch然后log再rethrow。毕竟如果用错误码的话,你anyway也需要有一段代码log(error)这个所谓的第一现场的。所以exception的工作量并不比错误码大,好处是在一个很深的调用里面,在你不需要第一现场的层上,完全不需要有error handling的代

    : ...................

    : 我其实不太理解你所说的第一现场。

    : 如果是throw的地方,你完全可以把需要的信息log(error)出来再throw,或者如果catch的地方需要这些值,可以把需要的信息加到exception里面去。

    : 如果是caller的地方,你也可以catch然后log再rethrow。毕竟如果用错误码的话,你anyway也需要有一段代码log(error)这个所谓的第一现场的。所以exception的工作量并不比错误码大,好处是在一个很深的调用里面,在你不需要第一现场的层上,完全不需要有error handling的代

    : ...................

    : 我其实不太理解你所说的第一现场。

    : 如果是throw的地方,你完全可以把需要的信息log(error)出来再throw,或者如果catch的地方需要这些值,可以把需要的信息加到exception里面去。

    : 如果是caller的地方,你也可以catch然后log再rethrow。毕竟如果用错误码的话,你anyway也需要有一段代码log(error)这个所谓的第一现场的。所以exception的工作量并不比错误码大,好处是在一个很深的调用里面,在你不需要第一现场的层上,完全不需要有error handling的代

    : ...................

    : log并不能取代exception。除非LOG(FATAL) << ...,否则程序还是继续得到执行(如果caller没有检查返回值),导致错误继续积累下去。

    : 而log(fatal)强制crash并不总是是最好的解决方案。因为有的时候错误不是致命的。比如一个server,由于query其他service的时候timeout了所以handle不了这个request,这样的错误至少不是致命的,还可以handle别的request。一个clean的方法就是在这里throw在request handler的最上面catch就好了。如果在一个很深的调用里面把错误码一层一层传上去,实在太恶心了。

    : 还有人说C++的exception不能有stack trace的信息,这个也是不对的。我看过有人写过一个.so,具体细节我不太清楚了,大致上是重新实现了C++ exception handling的ABI, 让它包含stacktrace的信息。然后LD_PRELOAD加载这个so的程序就可以有stacktrace了。可惜的是我找不到这个东西了。哪位知道的可以告诉我。

    : ...................

    : 好吧,我以为他说的是不杀进程的情况。不过貌似不杀进程用可以dump,只不过可能比log(error) heavy,毕竟要把整个memory写到文件里?

    : 他需要的是dump一个core文件

    : --

    : ...................

    : log并不能取代exception。除非LOG(FATAL) << ...,否则程序还是继续得到执行(如果caller没有检查返回值),导致错误继续积累下去。

    : 而log(fatal)强制crash并不总是是最好的解决方案。因为有的时候错误不是致命的。比如一个server,由于query其他service的时候timeout了所以handle不了这个request,这样的错误至少不是致命的,还可以handle别的request。一个clean的方法就是在这里throw在request handler的最上面catch就好了。如果在一个很深的调用里面把错误码一层一层传上去,实在太恶心了。

    : 还有人说C++的exception不能有stack trace的信息,这个也是不对的。我看过有人写过一个.so,具体细节我不太清楚了,大致上是重新实现了C++ exception handling的ABI, 让它包含stacktrace的信息。然后LD_PRELOAD加载这个so的程序就可以有stacktrace了。可惜的是我找不到这个东西了。哪位知道的可以告诉我。

    : ...................

    : 那不就直接好了crash了,错误码也没啥用了。

    : 他就是要把程序弄死,要那个 core dump

    : log并不能取代exception。除非LOG(FATAL) << ...,否则程序还是继续得到执行(如果caller没有检查返回值),导致错误继续积累下去。

    : 而log(fatal)强制crash并不总是是最好的解决方案。因为有的时候错误不是致命的。比如一个server,由于query其他service的时候timeout了所以handle不了这个request,这样的错误至少不是致命的,还可以handle别的request。一个clean的方法就是在这里throw在request handler的最上面catch就好了。如果在一个很深的调用里面把错误码一层一层传上去,实在太恶心了。

    : 还有人说C++的exception不能有stack trace的信息,这个也是不对的。我看过有人写过一个.so,具体细节我不太清楚了,大致上是重新实现了C++ exception handling的ABI, 让它包含stacktrace的信息。然后LD_PRELOAD加载这个so的程序就可以有stacktrace了。可惜的是我找不到这个东西了。哪位知道的可以告诉我。

    : ...................

    : 好吧,我以为他说的是不杀进程的情况。不过貌似不杀进程用可以dump,只不过可能比log(error) heavy,毕竟要把整个memory写到文件里?

    : 他需要的是dump一个core文件

    : --

    : ...................

    : log并不能取代exception。除非LOG(FATAL) << ...,否则程序还是继续得到执行(如果caller没有检查返回值),导致错误继续积累下去。

    : 而log(fatal)强制crash并不总是是最好的解决方案。因为有的时候错误不是致命的。比如一个server,由于query其他service的时候timeout了所以handle不了这个request,这样的错误至少不是致命的,还可以handle别的request。一个clean的方法就是在这里throw在request handler的最上面catch就好了。如果在一个很深的调用里面把错误码一层一层传上去,实在太恶心了。

    : 还有人说C++的exception不能有stack trace的信息,这个也是不对的。我看过有人写过一个.so,具体细节我不太清楚了,大致上是重新实现了C++ exception handling的ABI, 让它包含stacktrace的信息。然后LD_PRELOAD加载这个so的程序就可以有stacktrace了。可惜的是我找不到这个东西了。哪位知道的可以告诉我。

    : ...................

    : 不杀进程 dump 怎么做?

    : 我个人觉得从软件工程的角度而言返回错误码是一个不太好的设计。用起来繁琐不说,更严重的问题是允许调用者忽略错误码。一个很大的软件公司,招的都是很好的码农,有人对codebase做过统计,代码里面95%以上的需要检查的返回值的错误码都没有得到检查。

    : 比较好的方法就是使用expcetion,同时要求caller能够做到exception safe,比如用smart pointer,比如用RAII之类的。其实养成习惯之后,这些都很方便的。比如不用new和delete,而是用容器;比如new的指针用unique或者shared包起来,这样反而省了一行delete,何乐而不为呢?

    : C++异常应该用在那些无法返回错误码的地方,比如 operator[]()重载函数里,能用错误码表示的,尽量还是用C方式的错误码吧

    : ...................

    : 神马软件工程啊,有空多写代码吧

    : 错误处理方式有返回错误码,有longjump,有异常

    : 每种错误处理方式出来都不是对前面那种方式的代替,而是补充

    : ...................

    : 我个人觉得从软件工程的角度而言返回错误码是一个不太好的设计。用起来繁琐不说,更严重的问题是允许调用者忽略错误码。一个很大的软件公司,招的都是很好的码农,有人对codebase做过统计,代码里面95%以上的需要检查的返回值的错误码都没有得到检查。

    : 比较好的方法就是使用expcetion,同时要求caller能够做到exception safe,比如用smart pointer,比如用RAII之类的。其实养成习惯之后,这些都很方便的。比如不用new和delete,而是用容器;比如new的指针用unique或者shared包起来,这样反而省了一行delete,何乐而不为呢?

    : C++异常应该用在那些无法返回错误码的地方,比如 operator[]()重载函数里,能用错误码表示的,尽量还是用C方式的错误码吧

    : ...................

    : 觉得异常比错误码麻烦的,足下的审美颇为奇特。

    : 说我放空炮,我当码农也有些年头了,这些是从我的写过的和review过的许多代码,听过的 公司里世界级C++大牛上课的里总结的各种经验。

    : 至少我列了几条理由,说明错误码在现实中的问题。现实就是,即使是很好的软件公司和很优秀的码农,照样会不去处理错误码,更不要说那些一般般的码农了。没有开发经验的人才会觉得整个函数都是错误码处理的code会比较好维护,会产生质量更好的代码。而你只是武断下了几个结论而已,谁放空炮显而易见。

    : ...................

    : 我个人觉得从软件工程的角度而言返回错误码是一个不太好的设计。用起来繁琐不说,更严重的问题是允许调用者忽略错误码。一个很大的软件公司,招的都是很好的码农,有人对codebase做过统计,代码里面95%以上的需要检查的返回值的错误码都没有得到检查。

    : 比较好的方法就是使用expcetion,同时要求caller能够做到exception safe,比如用smart pointer,比如用RAII之类的。其实养成习惯之后,这些都很方便的。比如不用new和delete,而是用容器;比如new的指针用unique或者shared包起来,这样反而省了一行delete,何乐而不为呢?

    : C++异常应该用在那些无法返回错误码的地方,比如 operator[]()重载函数里,能用错误码表示的,尽量还是用C方式的错误码吧

    : ...................

    : 觉得异常比错误码麻烦的,足下的审美颇为奇特。

    : 说我放空炮,我当码农也有些年头了,这些是从我的写过的和review过的许多代码,听过的 公司里世界级C++大牛上课的里总结的各种经验。

    : 至少我列了几条理由,说明错误码在现实中的问题。现实就是,即使是很好的软件公司和很优秀的码农,照样会不去处理错误码,更不要说那些一般般的码农了。没有开发经验的人才会觉得整个函数都是错误码处理的code会比较好维护,会产生质量更好的代码。而你只是武断下了几个结论而已,谁放空炮显而易见。

    : ...................

    : 我个人觉得从软件工程的角度而言返回错误码是一个不太好的设计。用起来繁琐不说,更严重的问题是允许调用者忽略错误码。一个很大的软件公司,招的都是很好的码农,有人对codebase做过统计,代码里面95%以上的需要检查的返回值的错误码都没有得到检查。

    : 比较好的方法就是使用expcetion,同时要求caller能够做到exception safe,比如用smart pointer,比如用RAII之类的。其实养成习惯之后,这些都很方便的。比如不用new和delete,而是用容器;比如new的指针用unique或者shared包起来,这样反而省了一行delete,何乐而不为呢

    : C++异常应该用在那些无法返回错误码的地方,比如 operator[]()重载函数里,能用错误码表示的,尽量还是用C方式的错误码吧

    : ...................

    : 我个人觉得从软件工程的角度而言返回错误码是一个不太好的设计。用起来繁琐不说,更严重的问题是允许调用者忽略错误码。一个很大的软件公司,招的都是很好的码农,有人对codebase做过统计,代码里面95%以上的需要检查的返回值的错误码都没有得到检查。

    : 比较好的方法就是使用expcetion,同时要求caller能够做到exception safe,比如用smart pointer,比如用RAII之类的。其实养成习惯之后,这些都很方便的。比如不用new和delete,而是用容器;比如new的指针用unique或者shared包起来,这样反而省了一行delete,何乐而不为呢

    : C++异常应该用在那些无法返回错误码的地方,比如 operator[]()重载函数里,能用错误码表示的,尽量还是用C方式的错误码吧

    : ...................

    : 要求代码都写得 exception safe 也是一个很高的要求。工程上,规定返回值必须检查,比规定所有代码都要异常安全,执行起来容易得多。

    : C++ 里没有原生的 finally 支持,所有需要清理的情况都要搞一个类来做 RAII 很麻烦。好在 C++11 可以山寨类似 finally 的功能。

    : “下层的错误你不处理就不处理了.”可以被忽略的错误本来就不需要用异常。问题是大多数时候错误都不该被忽略。出了问题不去处理,程序还在按照正常情况的逻辑去执行,不出问题才怪呢。

    : “错误码处理写几句,异常处理也要写几句.”笑话。错误码每个地方都要检查返回值。异常只需要在最上面写一遍就行了。

    : “那种最后一个大try/catch的做法,和出错不处理,没啥区别.”当然有区别。“出错不处理”那是带错运行。“一个大try/catch”至少保证没有带错运行。在server里面,在最上面try catch,我能保证当前session及时终止,没有带错运行,资源正确释放。然后根据exeption的严重程度,决定是不是处理下一个session,还是终止程序。再说,你错误码能携带多少信息给上层?Exception又能携带多少信息给上层?孰优孰劣一目了然。

    : ...................

    : 即使用概括性的,那你也得

    : bool f() {

    : // blablabla

    : ...................

    : 异常安全太难了

    : 另外,RAII很难避免析构函数抛异常

    : finally里抛异常算什么...

    : 即使用概括性的,那你也得

    : bool f() {

    : // blablabla

    : ...................

    : 是否忽略是调用方决定的事,不是被调用方决定的事.

    : 你写下层函数的时候,怎么知道上层调用者是不是忽略?

    : 又怎么知道是该用错误码还是抛异常呢?

    : 上层函数调用下层3-5个函数,都有可能抛异常,难道不是不同的异常不同的处理么?

    : 错误码是分别处理。异常你写一遍什么意思?

    : 出错不处理,打点log, 最后程序崩掉。

    : 大try catch, 打点log, 最后程序结束。

    : 能有多大区别?那么深的层次,你能正确释放所有资源?

    : 异常强制上层云云,你只能强制自己,你能强制上层?

    : 还不是那句话,你不管你死屁了,反正我不管。

    : 检查错误码并作相应处理都嫌麻烦,能做到exception safe可能么?

    : 一个try/catch 然后忽略大部分异常,是通常做法吧。

    : 对于错误处理的覆盖,大概率低于用错误码的程序员。

    : 不知道啊,c++没有finally

    : 我一直觉得c++的异常安全就是摆设。既要通过构造析构管理资源,又不让析构函数抛异常(或者析构函数抛异常就破坏异常安全),这不是自己打自己脸么

    : 标  题: Re: 写库,弄很多异常,是不负责任的表现

    : 发信站: 水木社区 (Tue Mar 18 15:16:30 2014), 站内

    : 是否忽略是调用方决定的事,不是被调用方决定的事.

    : 你写下层函数的时候,怎么知道上层调用者是不是忽略?

    : 又怎么知道是该用错误码还是抛异常呢?

    : 上层函数调用下层3-5个函数,都有可能抛异常,难道不是不同的异常不同的处理么?

    : 错误码是分别处理。异常你写一遍什么意思?

    : 出错不处理,打点log, 最后程序崩掉。

    : 大try catch, 打点log, 最后程序结束。

    : 能有多大区别?那么深的层次,你能正确释放所有资源?

    : 异常强制上层云云,你只能强制自己,你能强制上层?

    : 还不是那句话,你不管你死屁了,反正我不管。

    : 检查错误码并作相应处理都嫌麻烦,能做到exception safe可能么?

    : 一个try/catch 然后忽略大部分异常,是通常做法吧。

    : 对于错误处理的覆盖,大概率低于用错误码的程序员。

    : 【 在 likanKyo (考完了...) 的大作中提到: 】

    : : “下层的错误你不处理就不处理了.”可以被忽略的错误本来就不需要用异常。问题是大多数时候错误都不该被忽略。出了问题不去处理,程序还在按照正常情况的逻辑去执行,不出问题才怪呢。

    : : “错误码处理写几句,异常处理也要写几句.”笑话。错误码每个地方都要检查返回值。异常只需要在最上面写一遍就行了。

    : : “那种最后一个大try/catch的做法,和出错不处理,没啥区别.”当然有区别。“出错不处理”那是带错运行。“一个大try/catch”至少保证没有带错运行。在server里面,在最上面try catch,我能保证当前session及时终止,没有带错运行,资源正确释放。然后根据exeption的严重程度,决定是不是处理下一个session,还是终止程序。再说,你错误码能携带多少信息给上层?Exception又能携带多少信息给上层?孰优孰劣一目了然。

    : : ...................

    : --

    : 标  题: Re: 写库,弄很多异常,是不负责任的表现

    : 发信站: 水木社区 (Tue Mar 18 15:16:30 2014), 站内

    : 是否忽略是调用方决定的事,不是被调用方决定的事.

    : 你写下层函数的时候,怎么知道上层调用者是不是忽略?

    : 又怎么知道是该用错误码还是抛异常呢?

    : 上层函数调用下层3-5个函数,都有可能抛异常,难道不是不同的异常不同的处理么?

    : 错误码是分别处理。异常你写一遍什么意思?

    : 出错不处理,打点log, 最后程序崩掉。

    : 大try catch, 打点log, 最后程序结束。

    : 能有多大区别?那么深的层次,你能正确释放所有资源?

    : 异常强制上层云云,你只能强制自己,你能强制上层?

    : 还不是那句话,你不管你死屁了,反正我不管。

    : 检查错误码并作相应处理都嫌麻烦,能做到exception safe可能么?

    : 一个try/catch 然后忽略大部分异常,是通常做法吧。

    : 对于错误处理的覆盖,大概率低于用错误码的程序员。

    : 【 在 likanKyo (考完了...) 的大作中提到: 】

    : : “下层的错误你不处理就不处理了.”可以被忽略的错误本来就不需要用异常。问题是大多数时候错误都不该被忽略。出了问题不去处理,程序还在按照正常情况的逻辑去执行,不出问题才怪呢。

    : : “错误码处理写几句,异常处理也要写几句.”笑话。错误码每个地方都要检查返回值。异常只需要在最上面写一遍就行了。

    : : “那种最后一个大try/catch的做法,和出错不处理,没啥区别.”当然有区别。“出错不处理”那是带错运行。“一个大try/catch”至少保证没有带错运行。在server里面,在最上面try catch,我能保证当前session及时终止,没有带错运行,资源正确释放。然后根据exeption的严重程度,决定是不是处理下一个session,还是终止程序。再说,你错误码能携带多少信息给上层?Exception又能携带多少信息给上层?孰优孰劣一目了然。

    : : ...................

    : --

    : 最后展开一下PGP所说的低效问题。就是错误码if-else这种错误处理方式的性能也不好,而且为了传递给上层,同错误处理无关的调用层次上也又要承受if-else的overhead。而且即使不发生错误,程序正常执行的情况下,也照样要承受相应的overhead。

    : 至于exception,现在的C++ compiler早就已经可以做到在不发生异常的时候没有overhead;相反,错误码即使在正常情况下还要执行if-else。

    : exception的一点overhead是阻止了编译器的进行code-movement的优化。但是只要被调用的函数不是在同一个CU里面,那这个优化是否能进行和调用函数是否真的会抛出异常无关,因为C++本来就默认是任何函数都可以抛出异常的,除非你非常蛋疼地给所有的函数都加上nothrow。

    : ...................

    : 直接用错误代码就行了 非要整个异常 把程序弄崩溃了

    : 不知道啊,c++没有finally

    : 我一直觉得c++的异常安全就是摆设。既要通过构造析构管理资源,又不让析构函数抛异常(或者析构函数抛异常就破坏异常安全),这不是自己打自己脸么

    : 标  题: Re: 写库,弄很多异常,是不负责任的表现

    : 发信站: 水木社区 (Tue Mar 18 19:48:11 2014), 站内

    : 总体来说,性能关键的地方使用错误码避免用异常

    : 错误检查频繁的地方用异常

    : 在关键的 api 设计上, 可能需要同时两套 api

    : 【 在 likanKyo (考完了...) 的大作中提到: 】

    : : 最后展开一下PGP所说的低效问题。就是错误码if-else这种错误处理方式的性能也不好,而且为了传递给上层,同错误处理无关的调用层次上也又要承受if-else的overhead。而且即使不发生错误,程序正常执行的情况下,也照样要承受相应的overhead。

    : : 至于exception,现在的C++ compiler早就已经可以做到在不发生异常的时候没有overhead;相反,错误码即使在正常情况下还要执行if-else。

    : : exception的一点overhead是阻止了编译器的进行code-movement的优化。但是只要被调用的函数不是在同一个CU里面,那这个优化是否能进行和调用函数是否真的会抛出异常无关,因为C++本来就默认是任何函数都可以抛出异常的,除非你非常蛋疼地给所有的函数都加上nothrow。

    : : ...................

    : --

    : 我可以很负责任地告诉你

    : 雷叔很生气,后果很严重

    : 你这回帖...感觉likankyo那洋洋洒洒一堆你都没看就回了...异常显然比用错误码有性

    : 能优势啊...

    : 异常需要记录局部对象好在异常抛出时作destructor,看不出来异常哪里有性能优势了

    : 那些有finally的语言,Java,C#,可以在finally里抛异常吗?

    : Java可以

    : 那Java里,在finally里抛了异常以后,抛出异常的语句后面那些释放资源的代码还会被

    : 调用吗?

    : 你这回帖...感觉likankyo那洋洋洒洒一堆你都没看就回了...异常显然比用错误码有性

    : 能优势啊...

    : 最后展开一下PGP所说的低效问题。就是错误码if-else这种错误处理方式的性能也不好,而且为了传递给上层,同错误处理无关的调用层次上也又要承受if-else的overhead。而且即使不发生错误,程序正常执行的情况下,也照样要承受相应的overhead。

    : 至于exception,现在的C++ compiler早就已经可以做到在不发生异常的时候没有overhead;相反,错误码即使在正常情况下还要执行if-else。

    : exception的一点overhead是阻止了编译器的进行code-movement的优化。但是只要被调用的函数不是在同一个CU里面,那这个优化是否能进行和调用函数是否真的会抛出异常无关,因为C++本来就默认是任何函数都可以抛出异常的,除非你非常蛋疼地给所有的函数都加上nothrow。

    : ...................

    : 错误码一旦需要debug,你得在所有错误处理的地方打印错误信息,你才能知道到底是哪里出了问题。exception就方便了,只要你把最上面的try-catch注释掉,程序崩溃了就能打stack trace,如果用-g -ggdb编译,你可以立刻知道是哪行抛的异常。比error code方便无数倍。

    : 我会告诉你glog这个利器么?

    : 等debug的时候 你就哭吧

    : ...................

    http://www.hpenterprisesecurity.com/vulncat/en/vulncat/java/poor_error_handling_throw_inside_finally.html

    : 异常和错误码如果实现完全一样的功能, 错误码的性能要更高

    : 主要与异常的实现机制有关系

    : 这个业界早有公论了

    : ...................

    : 这个公论的问题就在于 早,太早了,早 就不是这样了

    : 我真诚的建议你再认真读一遍likankyo那篇帖子

    : 举个例子来说, 我要做一个判断字符串是否是数字的函数

    : 有两种方案用返回值来标识:

    : 第一种:

    : ...................

    : 大概算一下,假设不查错程序运行时间是1,用了异常在正常流程下程序运行时间是1,异常发生的情况下运行时间夸张一点1.15吧,用错误码不管什么流程运行时间是1.01,假设异常发生的概率是千分之一,统计上运行一千次用异常的代码期待运行时间是1000.15, 而用错误码的代码

    : 很多年前就在说这个了

    : 问题就在于这个在不发生异常的情况下,性能没损失

    : 这种情况,只能用于错误不可恢复的情况

    : ...................

    : 呃,你这段话体现了对异常的最普遍的一种误解——即“异常是用于流程控制的”

    : 举个例子来说, 我要做一个判断字符串是否是数字的函数

    : 有两种方案用返回值来标识:

    : 第一种:

    : ...................

    : Int32.TryParse Method (String, Int32)

    : .NET Framework 4.5 Other Versions 21 out of 30 rated this helpful - Rate this topic

    : Converts the string representation of a number to its 32-bit signed integer equivalent. A return value indicates whether the conversion succeeded.

    : ...................

    : 那些有finally的语言,Java,C#,可以在finally里抛异常吗?

    : 我觉得“异常是用于异常流程控制的”应该没说错……

    : 标  题: Re: 写库,弄很多异常,是不负责任的表现

    : 发信站: 水木社区 (Wed Mar 19 10:12:14 2014), 站内

    : 允许,而且会break finally,这也是我认为异常的一个劣势,一个流程中只能有一个异常

    : 明确站个队吧,我认为C++异常是一个非常糟糕的设计,它只解决了一个问题,就是对于已经定义了返回值类型的函数,可以多一种返回的方式(比如构造函数、操作符重载就不得不用异常,dynamic_cast也不得不用异常,其他的例子类似)。就标准库中的实践来看,也仅仅是在不得不用的时候才用异常机制。我认为合理的用法是,尽量避免在以上情形中使用异常,让构造、析构、操作符都成为非常轻量级的运算。对可能产生异常的操作用合理的api设计来实现;对繁琐的错误码检查用合理的代码结构设计来避免。同时基于此,我认为用RAII管理外部资源也不是一个好的设计。我的建议是手动释放外部资源,RAII最多只用于调用轻量级的析构函数和释放内存。如果函数出口太多,那么就重构。

    : 对了,你会发现这种写法很像C。实际上我们能招聘到的90%以上的C++程序员,对C++的使用都仅限于C加上class,这也是最现实、最实际的用法。在现实环境中能够让代码有更好的可维护性。

    : 【 在 sunseraphic (この世界がいつかは幻に変わると) 的大作中提到: 】

    : : 那些有finally的语言,Java,C#,可以在finally里抛异常吗?

    : --

    : 我对此观点唯一的疑虑是这所谓的能招到的90%以上的C++程序员是否有足够的自觉和能

    : 力去重构。

    : ...................

    : 那些有finally的语言,Java,C#,可以在finally里抛异常吗?

    : “一个流程中只能有一个异常”,你用错误码就能返回多个错误码了么?

    : “它只解决了一个问题,就是对于已经定义了返回值类型的函数,可以多一种返回的方式”。我列举的那么多错误码的糟糕之处都被选择性无视了啊?

    : 重复下面的话十遍:“错误码允许被忽略,导致系统带错运行,系统不稳定;允许系统带错执行,导致出错位置和真正原因发生地点相距甚远,导致调试困难;错误码导致正常情况的执行逻辑和错误处理的逻辑混杂在一起,降低可读性;错误码携带信息有限;错误码在和错误无关的调

    : ...................

    : 大概算一下,假设不查错程序运行时间是1,用了异常在正常流程下程序运行时间是1,异常发生的情况下运行时间夸张一点1.15吧,用错误码不管什么流程运行时间是1.01,假设异常发生的概率是千分之一,统计上运行一千次用异常的代码期待运行时间是1000.15, 而用错误码的代码

    : “一个流程中只能有一个异常”,你用错误码就能返回多个错误码了么?

    : “它只解决了一个问题,就是对于已经定义了返回值类型的函数,可以多一种返回的方式”。我列举的那么多错误码的糟糕之处都被选择性无视了啊?

    : 重复下面的话十遍:“错误码允许被忽略,导致系统带错运行,系统不稳定;允许系统带错执行,导致出错位置和真正原因发生地点相距甚远,导致调试困难;错误码导致正常情况的执行逻辑和错误处理的逻辑混杂在一起,降低可读性;错误码携带信息有限;错误码在和错误无关的调

    : ...................

    : 所以说啊,我列举的这么多条理由都直接反驳了你的“它只解决了一个问题”的前提,所以你说的“异常处理是个糟糕的设计”也就站不住脚了。

    : 错误码作为上古时代,人们茹毛饮血的产物,放到现在有太多问题遭人诟病。异常很大程度上解决了这些问题,虽然也或多或少引入了一些新的问题。正如现代人的生活方式虽然也存在问题,虽然有地沟油和雾霾,但是没有人愿意回到原始社会过着没有电脑没有网络没有iPhone的生活

    : 所以所有的讨论关键点在于前提

    : ...................

    : 所以说啊,我列举的这么多条理由都直接反驳了你的“它只解决了一个问题”的前提,所以你说的“异常处理是个糟糕的设计”也就站不住脚了。

    : 错误码作为上古时代,人们茹毛饮血的产物,放到现在有太多问题遭人诟病。异常很大程度上解决了这些问题,虽然也或多或少引入了一些新的问题。正如现代人的生活方式虽然也存在问题,虽然有地沟油和雾霾,但是没有人愿意回到原始社会过着没有电脑没有网络没有iPhone的生活

    : 所以所有的讨论关键点在于前提

    : ...................

    : 我并不认为异常是个“非常”优秀的设计,只不过它是个完胜错误码的设计。

    : 将来或许会有比异常更好的设计出现。

    : 异常有它的问题,但是要回到错误码是不对的。

    : ...................

    : 我并不认为异常是个“非常”优秀的设计,只不过它是个完胜错误码的设计。

    : 将来或许会有比异常更好的设计出现。

    : 异常有它的问题,但是要回到错误码是不对的。

    : ...................

    : 对于异常和错误码比较,我记得有这么一句话,好像是error handling is evil, 反正意思

    : 另外关于错误码和异常性能的比较,可能还有另外一点因素,就是异常处理需要rtti的支

    : 即使用概括性的,那你也得

    : bool f() {

    : // blablabla

    : if (!doSomething()) {

    : return false;

    : }

    : ...................

    : 对于异常和错误码比较,我记得有这么一句话,好像是error handling is evil, 反正意思就是错误处理本来就是一件很脏的活,很多时候我们诟病异常不好,写起来不爽,团队不好执行,可是仔细想想,其实异常目前看已经算一个不错的错误处理的方案了,其他的方式,比如错误码

    : 另外关于错误码和异常性能的比较,可能还有另外一点因素,就是异常处理需要rtti的支持,这个rtti的支持需要额外的性能开销,而有些项目使用c++就是多了class(包括virtual method)的c,或者因为跨平台的因素,而没有打开rtti支持(就我知道好像qnx,还有wince的老编译器不�

    : 异常的逻辑是:出了错必须处理,你想吞掉错误不让上面知道,那就就得很麻烦

    : 错误码的逻辑是:出了错默认不处理。你要处理错误,就得很麻烦地一种情况一

    : 人都是懒的,所以这就是为什么我说的,一个大的软件公司,招的是很好的码

    : ...................

    : File f = File.open("1.txt");

    : if (!f.isOpen())) {

    :   return false;

    : }

    : if (!doSomething()) {

    : f.close();

    :   reutrn false;

    : }

    : if (!doSomething2()) {

    : f.close();

    :   return false;

    : }

    : 和

    : File f = File.open("1.txt");

    : SCOPE_EXIT { f.close(); };

    : doSomething();

    : doSomething2();

    : ...................

    : 写这段示例代码对于你的论点没有帮助,它们的功能不完全等同,你的 try ...

    : catch ... 在哪里?

    : 不知写这样的代码算不算懒:

    : ...................

    : 异常安全太难了

    : 另外,RAII很难避免析构函数抛异常

    : 你没看明白,他写的//blablabla是省略中间无数代码,不是注释。

    : “异常处理需要rtti的支持”,求详细,谢谢

    : catch 异常的时候,总是要知道异常的实际runtime type(typeid这些),这个需要打开rtti支持,在visual studio是/GR选项我记得

    : 据我所知,虽然异常的实现是会要求类型信息,但是RTTI的支持不是同时需要的,否则

    : 关闭了RTTI的情况下异常怎么实现。

    : 至于要求具备类型信息的异常实现是否会导致你说的运行时性能开销倒是可以讨论——基

    : ...................

    : 标  题: Re: 写库,弄很多异常,是不负责任的表现

    : 发信站: 水木社区 (Thu Mar 20 01:01:33 2014), 站内

    : 刚才仔细查了一下,确实rtti支持是不需要的,人云亦云了,听同事前阵子讨论是否在项目中支持exception的时候提了这个,我自己没具体查就信了-,-

    : 具体对象的类型信息检查的开销也还仅仅是在异常产生需要处理以后才会发生的,这个开销正常处理的时候是不需要的吧

    : 至于具体对象的类型信息应该是c++本来就必须支持的吧

    : 这个我还想具体问一句,好像rtti的额外开销挺大的,具体是dynamic_cast, typeinfo()之类的,为啥呢?这些信息难道不是对象信息里面必须携带的么?

    : 【 在 sunseraphic 的大作中提到: 】

    : : 据我所知,虽然异常的实现是会要求类型信息,但是RTTI的支持不是同时需要的,否则

    : : 关闭了RTTI的情况下异常怎么实现。

    : : 至于要求具备类型信息的异常实现是否会导致你说的运行时性能开销倒是可以讨论——基

    : : ...................

    : --

    : 简单的说,C++不支持反射,所以一个用户自定义类型的对象一般是不带其自身类型信息

    : 的(当然内置类型就更不带了),但是对于面向对象编程,运行时的类型信息又是必要

    : 的,所以最低限度的,对于拥有虚函数的对象而言起码是有虚表的,更多的运行时类型

    : ...................

    : 这个问题More Effective C++讲的清清楚楚,这里这么多人搞C++的,居然没人抬出这

    : 本神作!

    : ...................

    : 也就是说rtti的开销复杂度其实就是虚标的开销复杂度,是么?

    : 仅仅就因为typeinfo()这个函数的要求编译器保存了更多的类型信息,但是有rtti的虚表在query上的开销和没有rtti是一样的,这么理解对吧 ?

    : 虚(函数)机制本身属于RTTI的一部分...

    : 即使用概括性的,那你也得

    : bool f() {

    : // blablabla

    : if (!doSomething()) {

    : return false;

    : }

    : ...................

    : 异常的逻辑是:出了错必须处理,你想吞掉错误不让上面知道,那就就得很麻烦

    : 错误码的逻辑是:出了错默认不处理。你要处理错误,就得很麻烦地一种情况一

    : 人都是懒的,所以这就是为什么我说的,一个大的软件公司,招的是很好的码

    : ...................

    : File f = File.open("1.txt");

    : if (!f.isOpen())) {

    :   return false;

    : }

    : if (!doSomething()) {

    : f.close();

    :   reutrn false;

    : }

    : if (!doSomething2()) {

    : f.close();

    :   return false;

    : }

    : 和

    : File f = File.open("1.txt");

    : SCOPE_EXIT { f.close(); };

    : doSomething();

    : doSomething2();

    : ...................

    : 允许,而且会break finally,这也是我认为异常的一个劣势,一个流程中只能有一个异常

    : 明确站个队吧,我认为C++异常是一个非常糟糕的设计,它只解决了一个问题,就是对于已经定义了返回值类型的函数,可以多一种返回的方式(比如构造函数、操作符重载就不得不用异常,dynamic_cast也不得不用异常,其他的例子类似)。就标准库中的实践来看,也仅仅是在不得�

    : 对了,你会发现这种写法很像C。实际上我们能招聘到的90%以上的C++程序员,对C++的使用都仅限于C加上class,这也是最现实、最实际的用法。在现实环境中能够让代码有更好的可维护性。

    : ...................

    : 就我自己在工作中的感受,很多c++程序员因为以前大多是写c的,所以很饭C的那一套,很多用class就和struct一样,继承也仅仅是因为复用代码,OOP, s.o.l.i.d.那些东西很多都没有概念

    : 我个人觉得从软件工程的角度而言返回错误码是一个不太好的设计。用起来繁琐不说,更严重的问题是允许调用者忽略错误码。一个很大的软件公司,招的都是很好的码农,有人对codebase做过统计,代码里面95%以上的需要检查的返回值的错误码都没有得到检查。

    : 比较好的方法就是使用expcetion,同时要求caller能够做到exception safe,比如用smart pointer,比如用RAII之类的。其实养成习惯之后,这些都很方便的。比如不用new和delete,而是用容器;比如new的指针用unique或者shared包起来,这样反而省了一行delete,何乐而不为呢?

    : C++异常应该用在那些无法返回错误码的地方,比如 operator[]()重载函数里,能用错误码表示的,尽量还是用C方式的错误码吧

    : 我也这么认为的,但是为啥可以用virtual method,但是关闭rtti支持呢?应该说rtti有不同层次的支持吧

    : c++的异常悲催在从接口看不出有没有异常会抛出来

    : 【 在 likanKyo (考完了...) 的大作中提到: 】

    : C++11 很容易发现,默认挂掉:析构函数默认noexcept——只要没有显式声明抛异常,而直接或间接抛了异常,那么就意味着std::terminate。

    : 你说的这种本质还是C程序员呀,哈哈

    : 哪种语言的接口声明里包含了方法的异常规格?

    : java就有啊

    : public interface Closeable {

    :     public void close() throws IOException;

    : ...................

    : 事实上能招聘到的很多都是C程序员

    : 优秀的C++程序员基本都去Google了,招一些底子还不错,凑合用,听话又好干活的程序员是绝大多数公司的现状,也是最现实、最经济的选择

    : 后果无非就是代码没那么现代化,像是上个世纪的,who cares。

    : ...................

    : 我记得你现在是Dieken的同事吧?

    : 嘿,看ip还真是。。

    : 但我现在写java。。。

    : 囧。。。09年拿过你们家offer。。。当时和郑皓谈的。。。

    : 那时候george chu还是我的顶头上司。。。结果他现在倒是去了你们那儿。。。

    : 事实上能招聘到的很多都是C程序员

    : 优秀的C++程序员基本都去Google了,招一些底子还不错,凑合用,听话又好干活的程

    : 后果无非就是代码没那么现代化,像是上个世纪的,who cares。

    : 哪种语言的接口声明里包含了方法的异常规格?

    : java好像有

    : 直接用错误代码就行了 非要整个异常 把程序弄崩溃了

    : 有一个疑问:

    : 如下函数

    : int DownloadAndProcess(url)

    : ...................

    : 有一个疑问:

    : 如下函数

    : int DownloadAndProcess(url)

    : ...................

    : 事实上能招聘到的很多都是C程序员

    : 优秀的C++程序员基本都去Google了,招一些底子还不错,凑合用,听话又好干活的程序员是绝大多数公司的现状,也是最现实、最经济的选择

    : 后果无非就是代码没那么现代化,像是上个世纪的,who cares。

    : ...................

    : 直接用错误代码就行了 非要整个异常 把程序弄崩溃了

    : 你说功能不一样?当然是一样的。功能就是把下面的错误向上传递。对于异常处理,

    : 种情况下我本来就不需要try-catch,

    : 再说了,我这里也是省略了doSomething()和doSomething2()之间的“//blabla”,

    : ...................

    : 有一个疑问:

    : 如下函数

    : int DownloadAndProcess(url)

    : ...................

    : 构造函数咋整?

    : 虚(函数)机制本身属于RTTI的一部分...

    : 如果对象在构造时发生了错误,可以把错误信息存储在类成员变量中,通过公有函数对

    : 外提供错误信息。

    : 或者把会发生错误的代码,从构造函数移出,封装成有返回值的初始化函数。

    : ...................

    : 如果对象在构造时发生了错误,可以把错误信息存储在类成员变量中,通过公有函数对

    : 外提供错误信息。

    : 或者把会发生错误的代码,从构造函数移出,封装成有返回值的初始化函数。

    : ...................

    : int DownloadAndProcess(url) 函数需要定义自己的错误码。

    : 如果你很懒,或者没有分辨详细错误信息的必要,可以只定义失败和成功的错误码,例

    : 如 0 表示成功,-1 表示失败。

    : ...................

    : 如果对象在构造时发生了错误,可以把错误信息存储在类成员变量中,通过公有函数对

    : 外提供错误信息。

    : 或者把会发生错误的代码,从构造函数移出,封装成有返回值的初始化函数。

    : ...................

    : 除了你说的增加代码还有别的好处吗?贵公司是按行算钱?

    : 有时候0是成功,有时候true是成功,有时候exe_ok是成功,有时候no_error是成

    : 构造都没成功,还能用类成员变量?

    : 构造都没成功,还能用类成员变量?

    : 标  题: Re: 写库,弄很多异常,是不负责任的表现

    : 发信站: 水木社区 (Fri Mar 21 18:11:44 2014), 站内

    : 直接好处是创建对象时不用捕捉异常

    : 【 在 PGP (---) 的大作中提到: 】

    : : 除了你说的增加代码还有别的好处吗?贵公司是按行算钱?

    : --

    Gentlemen, start your engines!

    : 标  题: Re: 写库,弄很多异常,是不负责任的表现

    : 发信站: 水木社区 (Fri Mar 21 18:26:58 2014), 站内

    : 对象在构造时发生了错误,对象的属性可能不是正常的值,这不表示对象没有被创建。

    : 【 在 worklife (work & life) 的大作中提到: 】

    : : 构造都没成功,还能用类成员变量?

    : --

    Gentlemen, start your engines!

    : 有一个疑问:

    : 如下函数

    : int DownloadAndProcess(url)

    : ...................

    : c++的异常悲催在从接口看不出有没有异常会抛出来

    : --

    : 标  题: Re: 写库,弄很多异常,是不负责任的表现

    : 发信站: 水木社区 (Sat Mar 22 15:30:15 2014), 站内

    : 这种应该用状态流程图对业务流程进行设计 而不是依赖异常

    : 如果我做  一个错误报告就会生成 写入当前状态控制器

    : 状态控制器可以做成一个全局变量object

    : DownloadAndProcess 返回 bool值 就可以,要么完成了 要么处错了

    : int DownloadAndProcess(url)

    : {

    :      int err = Download(url, file); //下载文件到磁盘

    :      // err可能值: ERR_NETWORKING, ERR_URL_NOT_FOUND, ERR_FILE_ACCESS ....

    :      //此处如果err有错, 返回什么? 返回自定义的错误码, 还是Download的错误码?

    :      int err2 = Process(file); //业务逻辑处理

    :      // err2可能值: ERR_FILE_ACCESS, ERR_FILE_FORMAT, ERR_FILE_TOO_LARGE ...

    :      // 此处如果err2有错, 返回什么? 返回自定义的错误码, 还是Process的错误码?

    : }

    : 【 在 Elric 的大作中提到: 】

    : : 有一个疑问:

    : : 如下函数

    : : int DownloadAndProcess(url)

    : : ...................

    : --

    : 直接用错误代码就行了 非要整个异常 把程序弄崩溃了

    : C++里要把异常用好太困难了

    : boost里都一堆问题

    : 因此,对大部分c++程序员来说,最安全的方式,禁止使用异常

    : ...................

    : 不不不,最安全的方式是禁止使用C++

    : 不不不,最安全的方式是禁止使用C++

    2017-05-14
  • [合集] C++ 中如何实现终端无回显输入?

    ☆─────────────────────────────────────☆

     easior (lars) 于  (Mon Apr 10 11:57:54 2017)  提到:

    网上看了一下都是平台相关的,且是 C 代码,

    有没有平台无光的 C++ 代码实现?

    谢谢!

    ☆─────────────────────────────────────☆

     milksea (肥了,又肥了 >>>_<<<) 于  (Mon Apr 10 12:27:22 2017)  提到:

    标准库没有。

    不过 curses 有 windows 下的实现,即 PDCurses。

    只用到一两个函数自己把平台相关代码包一下也可以。

    只是无回显输入而已,C 代码问题不大吧。调用还方便。

    ☆─────────────────────────────────────☆

     easior (lars) 于  (Mon Apr 10 19:55:15 2017)  提到:

    多谢了!

    【 在 milksea (肥了,又肥了 >>>_<<<) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Sat May  6 09:40:30 2017)  提到:

    监控输入,读取后马上输出'\b'行不行?

    【 在 easior 的大作中提到: 】

    ☆─────────────────────────────────────☆

     easior (lars) 于  (Sat May  6 09:43:14 2017)  提到:

    这个太高端了,我不会啊。

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     origin008 (Origin) 于  (Sat May  6 11:07:06 2017)  提到:

    那就用C的标准库吧

    好像是getch函数?

    【 在 easior 的大作中提到: 】

    ☆─────────────────────────────────────☆

     easior (lars) 于  (Sat May  6 11:18:08 2017)  提到:

    多谢!

    这个是 MS Visual C++ 扩展,不是标准库。

    【 在 origin008 (Origin) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     liangyue (高级动物) 于  (Thu May 11 10:20:18 2017)  提到:

    可以的。以前这么玩过。

    在字符模式下,可以做出简单的类似动画的效果。

    【 在 origin008 的大作中提到: 】

    ☆─────────────────────────────────────☆

     vonNeumann (劣币驱逐良币 | 少灌水) 于  (Thu May 11 10:41:02 2017)  提到:

    楼主要求平台无关代码。

    这种做法需要干掉行缓冲,平台无关代码做不到。(setvbuf 不行,它只能干掉 C 库里的缓冲,干不掉终端的输入缓冲)

    【 在 liangyue (高级动物) 的大作中提到: 】

    【 在 easior (lars) 的大作中提到: 】

    : 网上看了一下都是平台相关的,且是 C 代码,

    : 有没有平台无光的 C++ 代码实现?

    : 谢谢!

    : ...................

    : 标准库没有。

    : 不过 curses 有 windows 下的实现,即 PDCurses。

    : 只用到一两个函数自己把平台相关代码包一下也可以。

    : ...................

    : 网上看了一下都是平台相关的,且是 C 代码,

    : 有没有平台无光的 C++ 代码实现?

    : 谢谢!

    : 监控输入,读取后马上输出'\b'行不行?

    : 这个太高端了,我不会啊。

    : 那就用C的标准库吧

    : 好像是getch函数?

    : 监控输入,读取后马上输出'\b'行不行?

    : 标  题: Re: C++ 中如何实现终端无回显输入?

    : 发信站: 水木社区 (Thu May 11 10:20:18 2017), 站内

    : 可以的。以前这么玩过。

    : 在字符模式下,可以做出简单的类似动画的效果。

    : 【 在 origin008 的大作中提到: 】

    : : 监控输入,读取后马上输出'\b'行不行?

    : :

    : --

    2017-05-14
  • [合集] 在代码里看到一条孤单的new语句

    ☆─────────────────────────────────────☆

     dpblue (deep blue) 于  (Thu Jun 13 09:24:47 2013)  提到:

    new A();

    没有任何赋值

    问题:

    1、这句话有什么用吗?

    2、这句话会带来内存泄漏吗?

    ☆─────────────────────────────────────☆

     milksea (肥了,又肥了 >>>_<<<) 于  (Thu Jun 13 09:33:03 2013)  提到:

    1、调用 A 的构造函数

    2、会

    ☆─────────────────────────────────────☆

     cppgx (s# 巛) 于  (Thu Jun 13 09:33:06 2013)  提到:

    无非是调用了一个函数并且忽略了返回值。

    可能有用,也可能没用;可能有内存泄漏,也可能没内存泄漏。

    【 在 dpblue (deep blue) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     milksea (肥了,又肥了 >>>_<<<) 于  (Thu Jun 13 09:34:02 2013)  提到:

    话说什么时候不内存泄漏?

    【 在 cppgx (s# 巛) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     cppgx (s# 巛) 于  (Thu Jun 13 09:35:30 2013)  提到:

    很显然的。

    【 在 milksea (肥了,又肥了 >>>_<<<) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     justicezyx (又跑路在即) 于  (Thu Jun 13 09:38:53 2013)  提到:

    也就是在您的大脑里面很显然的。。。

    照语言标准妥妥的未释放的内存。。。话说泄露都是结果,就好比java,简直可以成为controled mem leak。。。不也搞得挺欢么。。。

    【 在 cppgx 的大作中提到: 】

    ☆─────────────────────────────────────☆

     cppgx (s# 巛) 于  (Thu Jun 13 09:47:11 2013)  提到:

    A::A()

    {

    fork_music_player();

    on_sigchld(music_player, delete_this);

    }

    【 在 justicezyx (又跑路在即) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     mumford (化萝莉为大妈,化正太为大叔) 于  (Thu Jun 13 09:51:03 2013)  提到:

    不会泄露吧,不是退出自动析构了么?

    【 在 dpblue (deep blue) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sammychen (WA_KA_KA) 于  (Thu Jun 13 10:05:13 2013)  提到:

    可能是忘了删了;有内存泄露。

    【 在 dpblue (deep blue) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     skydoom (风险管理金融工程) 于  (Thu Jun 13 10:06:48 2013)  提到:

    想了一下,如果A里面有non-trival destructor,那么想依赖delete this 来清理内存可能是冒险的。

    【 在 cppgx (s# 巛) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     leslin (我心有约) 于  (Thu Jun 13 11:42:12 2013)  提到:

    【 在 milksea 的大作中提到: 】

    很多trick可以实现,比如new被重载的时候,比如构造函数里在一个地方保存了this。。。C++这种变态的语言,可以做很多神经不正常的事

    ☆─────────────────────────────────────☆

     javaboy (喝了咖啡就话多-_-;) 于  (Thu Jun 13 12:06:38 2013)  提到:

    #define new int  //我闪~

    【 在 milksea (肥了,又肥了 >>>_<<<) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     javaboy (喝了咖啡就话多-_-;) 于  (Thu Jun 13 12:10:28 2013)  提到:

    能写出 new A(); 的人肯定无所谓,谁会爱上谁。。

    【 在 skydoom (风险管理金融工程) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     milksea (肥了,又肥了 >>>_<<<) 于  (Thu Jun 13 12:56:54 2013)  提到:

    其实这个我问的时候想到了,还有 delete this 这种东西,但觉得不算正常用法

    【 在 cppgx (s# 巛) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     dpblue (deep blue) 于  (Thu Jun 13 13:58:27 2013)  提到:

    你这个说得很对啊,我刚才终于发现了,果然是在构造函数里保存了this:

    lazy_tls.Pointer()->Set(this);

    看来是由这个lazy_tls来释放这个对象了

    这个是Chrome的源代码,有兴趣的可以看这里:

    https://code.google.com/p/chromium/codesearch#chromium/src/content/renderer/render_thread_impl.cc&q=RenderThreadImpl::init&sq=package:chromium&l=342

    【 在 leslin (我心有约) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     skydoom (风险管理金融工程) 于  (Fri Jun 14 01:32:53 2013)  提到:

    这个影响太大了,很可能是 ub

    【 在 javaboy (喝了咖啡就话多-_-;) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     skydoom (风险管理金融工程) 于  (Fri Jun 14 01:46:46 2013)  提到:

    赶脚这里的用法不是很好。。。如果你看它的Shutdown()成员函数-->

    lazy_tls.Pointer()->Set(NULL);

    // Leak shared contexts on other threads, as we can not get to the correct

    // thread to destroy them.

    if (shared_contexts_compositor_thread_.get())

    shared_contexts_compositor_thread_->set_leak_on_destroy();

    可以看到,Set(NULL)内部应该是delete this 了(如果不是,那么就是一个highly possible memory leak bug),但是下面还尝试读取member shard_contexts_compositor_thread_....这个是UB哦。

    【 在 dpblue (deep blue) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     dpblue (deep blue) 于  (Fri Jun 14 09:34:46 2013)  提到:

    弱问UB是啥

    【 在 skydoom (风险管理金融工程) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     libgcc (传说中的动态库) 于  (Fri Jun 14 09:52:22 2013)  提到:

    undefined behavor

    【 在 dpblue (deep blue) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     justicezyx (又跑路在即) 于  (Fri Jun 14 10:40:12 2013)  提到:

    这下确实是显然了

    【 在 cppgx 的大作中提到: 】

    ☆─────────────────────────────────────☆

     roamer2889 (F458) 于  (Fri Jun 14 12:19:16 2013)  提到:

    c++就毁在你们这种人手里,成天玩弄奇技淫巧,明明可以有很简单容易懂的方式实现的东西,非要炫技,别忘记写程序的目的是要解决问题,而不是比拼代码炫。

    【 在 cppgx (s# 巛) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     ironmoon (183) 于  (Fri Jun 14 13:04:13 2013)  提到:

    肯定有内存泄漏~

    【 在 dpblue (deep blue) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     speedmancs (活好每一天) 于  (Fri Jun 14 13:11:57 2013)  提到:

    记得mfc的代码里就有这么搞的。。。

    【 在 leslin 的大作中提到: 】

    ☆─────────────────────────────────────☆

     einsnabuck (爱家爱老婆) 于  (Fri Jun 14 17:03:57 2013)  提到:

    同意

    【 在 roamer2889 的大作中提到: 】

    ☆─────────────────────────────────────☆

     orangetouch (橙色接触) 于  (Fri Jun 14 17:26:23 2013)  提到:

    class A

    无虚函数无成员变量

    new A() 时会占用内存么?

    ☆─────────────────────────────────────☆

     libgcc (传说中的动态库) 于  (Fri Jun 14 17:40:22 2013)  提到:

    【 在 orangetouch (橙色接触) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     cppgx (s# 巛) 于  (Fri Jun 14 17:49:03 2013)  提到:

    只不过违反一下“谁分配,谁释放”的原则,就扣个卖淫的帽子,大了。

    【 在 roamer2889 (F458) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     skydoom (风险管理金融工程) 于  (Fri Jun 14 18:24:47 2013)  提到:

    这个真不一定。。。不过no code no truth.

    【 在 ironmoon (183) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     einsnabuck (爱家爱老婆) 于  (Fri Jun 14 20:47:22 2013)  提到:

    这种,开源软件玩玩就好了,客户端软件也是.如果是服务器软件,特别是电信产品,不只是帽子这么简单,赔钱都要.

    【 在 cppgx 的大作中提到: 】

    ☆─────────────────────────────────────☆

     xuaa1 (xuaa1) 于  (Fri Jun 14 21:04:16 2013)  提到:

    最小1字节?

    【 在 orangetouch (橙色接触) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     cppgx (s# 巛) 于  (Fri Jun 14 21:43:14 2013)  提到:

    1字节就能存个指针?这种系统还需要内存管理么。

    【 在 xuaa1 (xuaa1) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     cppgx (s# 巛) 于  (Fri Jun 14 21:46:52 2013)  提到:

    我发现华强北出来的人容易不知道自己吃几碗干饭,净拿些奇葩的鸡毛当令箭。

    前不久那个“用int作参数的都去死”的也是。

    【 在 einsnabuck (爱家爱老婆) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     einsnabuck (爱家爱老婆) 于  (Fri Jun 14 21:53:37 2013)  提到:

    只是标识一下,根本不是指针.你可以写一个空类看看.

    【 在 cppgx 的大作中提到: 】

    ☆─────────────────────────────────────☆

     einsnabuck (爱家爱老婆) 于  (Fri Jun 14 21:54:22 2013)  提到:

    你的意思?

    【 在 cppgx 的大作中提到: 】

    ☆─────────────────────────────────────☆

     lijiangshui (经熟悟用巧新) 于  (Fri Jun 14 22:19:26 2013)  提到:

    Qt要泪奔了

    【 在 roamer2889 (F458) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     zerox (幽灵) 于  (Sat Jun 15 01:08:14 2013)  提到:

    C++不允许类的 sizeof 结果为 0,所以一般编译器实现是会给

    空结构体1个字节的空间。

    sizeof 为0的一个明显问题就是 TYPE arr[10]; 所有元素

    的地址都一样了。

    C 应该不允许空结构体。但是GCC好像有扩展,可以定义

    空结构体,对其 sizeof 也正是 0 ,囧。

    【 在 xuaa1 (xuaa1) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     javaboy (喝了咖啡就话多-_-;) 于  (Sat Jun 15 01:15:27 2013)  提到:

    这个不是UB啊,应该就是普通的B。。。

    【 在 skydoom (风险管理金融工程) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     cppgx (s# 巛) 于  (Sat Jun 15 01:42:04 2013)  提到:

    内存管理没开销?聪明。

    【 在 einsnabuck (爱家爱老婆) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     edyfox (滇狐) 于  (Sat Jun 15 08:00:53 2013)  提到:

    他的意思是说这种写法属于常见 idiom,不算奇技淫巧。如果这种写法都严格规定

    不让用,那是机械教条主义。

    【 在 einsnabuck (爱家爱老婆) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     vonNeumann (Sh) 于  (Sat Jun 15 09:03:13 2013)  提到:

    据说按标准 #define 关键字是 UB,不过现实中的预处理器应该都没问题

    【 在 javaboy (喝了咖啡就话多-_-;) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     zdjnju (埋下理想的种子,浇水浇水浇水∞) 于  (Sat Jun 15 10:05:45 2013)  提到:

    C++真是个蛋疼的语言,objc都比它好用

    ☆─────────────────────────────────────☆

     xuaa1 (xuaa1) 于  (Sat Jun 15 23:42:01 2013)  提到:

    内存管理是os的事情,和c++语言内对象大小不是一回事吧

    【 在 cppgx 的大作中提到: 】

    ☆─────────────────────────────────────☆

     cppgx (s# 巛) 于  (Sun Jun 16 01:32:10 2013)  提到:

    【 在 xuaa1 (xuaa1) 的大作中提到: 】

    他问的是会不会占内存。你哪只眼看见是问的对象大小?

    【 在 orangetouch (橙色接触) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     javaboy (喝了咖啡就话多-_-;) 于  (Sun Jun 16 14:44:21 2013)  提到:

    好像msvc自己也在用。。类似这样的

    #ifdef _DEBUG

    # define new DEBUG_NEW

    #endif

    【 在 vonNeumann (Sh) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     libgcc (传说中的动态库) 于  (Mon Jun 17 10:40:52 2013)  提到:

    我瞎了...

    【 在 zdjnju (埋下理想的种子,浇水浇水浇水∞) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     skydoom (风险管理金融工程) 于  (Mon Jun 17 22:07:33 2013)  提到:

    胡乱猜想,这个是编译器自己define,它应该很清楚DEBUG_NEW应该做什么(也就是说它能保证DEBUG_NEW能完全符合new的requirement). 但是如果是用户自定义DEBUG_NEW的话,很可能就不能做到这种保证,因此也就很可能是UB了。

    note, UB 不一定就是错误的行为,也有可能(在该种实现上)是正确的...

    【 在 javaboy (喝了咖啡就话多-_-;) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     DenyLewd (1983的小巷) 于  (Mon Jun 24 13:03:41 2013)  提到:

    可能你写程序目的是解决问题 不代表别人

    【 在 roamer2889 (F458) 的大作中提到: 】

    【 在 dpblue (deep blue) 的大作中提到: 】

    : new A();

    : 没有任何赋值

    : 问题:

    : 1、这句话有什么用吗?

    : 2、这句话会带来内存泄漏吗?

    : new A();

    : 没有任何赋值

    : 问题:

    : 1、这句话有什么用吗?

    : 2、这句话会带来内存泄漏吗?

    : 无非是调用了一个函数并且忽略了返回值。

    : 可能有用,也可能没用;可能有内存泄漏,也可能没内存泄漏。

    : 话说什么时候不内存泄漏?

    : 很显然的。

    : 也就是在您的大脑里面很显然的。。。

    : 照语言标准妥妥的未释放的内存。。。话说泄露都是结果,就好比java,简直可以成为controled mem leak。。。不也搞得挺欢么。。。

    : new A();

    : 没有任何赋值

    : 问题:

    : ...................

    : new A();

    : 没有任何赋值

    : 问题:

    : ...................

    : A::A()

    : {

    :     fork_music_player();

    : ...................

    : 话说什么时候不内存泄漏?

    : 话说什么时候不内存泄漏?

    : 想了一下,如果A里面有non-trival destructor,那么想依赖delete this 来清理内存可能是冒险的。

    : A::A()

    : {

    :     fork_music_player();

    : ...................

    : 很多trick可以实现,比如new被重载的时候,比如构造函数里在一个地方保存了this。。。C++这种变态的语言,可以做很多神经不正常的事

    : #define new int  //我闪~

    : 你这个说得很对啊,我刚才终于发现了,果然是在构造函数里保存了this:

    :   lazy_tls.Pointer()->Set(this);

    : 看来是由这个lazy_tls来释放这个对象了

    : ...................

    : 标  题: Re: 在代码里看到一条孤单的new语句

    : 发信站: 水木社区 (Fri Jun 14 01:46:46 2013), 站内

    : 赶脚这里的用法不是很好。。。如果你看它的Shutdown()成员函数-->

    :   lazy_tls.Pointer()->Set(NULL);

    :   // Leak shared contexts on other threads, as we can not get to the correct

    :   // thread to destroy them.

    :   if (shared_contexts_compositor_thread_.get())

    :     shared_contexts_compositor_thread_->set_leak_on_destroy();

    : 可以看到,Set(NULL)内部应该是delete this 了(如果不是,那么就是一个highly possible memory leak bug),但是下面还尝试读取member shard_contexts_compositor_thread_....这个是UB哦。

    : 【 在 dpblue (deep blue) 的大作中提到: 】

    : : 你这个说得很对啊,我刚才终于发现了,果然是在构造函数里保存了this:

    : :   lazy_tls.Pointer()->Set(this);

    : : 看来是由这个lazy_tls来释放这个对象了

    : : ...................

    : --

    : 您被管理员取消了本版的发文权限

    : 弱问UB是啥

    : A::A()

    : {

    :     fork_music_player();

    : ...................

    : A::A()

    : {

    :     fork_music_player();

    : ...................

    : new A();

    : 没有任何赋值

    : 问题:

    : ...................

    : 很多trick可以实现,比如new被重载的时候,比如构造函数里在一个地方保存了this。。。C++这种变态的语言,可以做很多神经不正常的事

    : c++就毁在你们这种人手里,成天玩弄奇技淫巧,明明可以有很简单容易懂的方式实现的东西,非要炫技,别忘记写程序的目的是要解决问题,而不是比拼代码炫。

    : class A

    : 无虚函数无成员变量

    : new A() 时会占用内存么?

    : ...................

    : c++就毁在你们这种人手里,成天玩弄奇技淫巧,明明可以有很简单容易懂的方式实现的东西,非要炫技,别忘记写程序的目的是要解决问题,而不是比拼代码炫。

    : 肯定有内存泄漏~

    : 只不过违反一下“谁分配,谁释放”的原则,就扣个卖淫的帽子,大了。

    : class A

    : 无虚函数无成员变量

    : new A() 时会占用内存么?

    : 标  题: Re: 在代码里看到一条孤单的new语句

    : 发信站: 水木社区 (Fri Jun 14 21:04:16 2013), 站内

    : 最小1字节?

    : 【 在 orangetouch (橙色接触) 的大作中提到: 】

    : : class A

    : : 无虚函数无成员变量

    : : new A() 时会占用内存么?

    : --

    : ^_^

    : 标  题: Re: 在代码里看到一条孤单的new语句

    : 发信站: 水木社区 (Fri Jun 14 20:47:22 2013), 站内

    : 这种,开源软件玩玩就好了,客户端软件也是.如果是服务器软件,特别是电信产品,不只是帽子这么简单,赔钱都要.

    : 【 在 cppgx 的大作中提到: 】

    : : 只不过违反一下“谁分配,谁释放”的原则,就扣个卖淫的帽子,大了。

    : :

    : --

    : 1字节就能存个指针?这种系统还需要内存管理么。

    : 我发现华强北出来的人容易不知道自己吃几碗干饭,净拿些奇葩的鸡毛当令箭。

    : 前不久那个“用int作参数的都去死”的也是。

    : c++就毁在你们这种人手里,成天玩弄奇技淫巧,明明可以有很简单容易懂的方式实现的东西,非要炫技,别忘记写程序的目的是要解决问题,而不是比拼代码炫。

    : 最小1字节?

    : 标  题: Re: 在代码里看到一条孤单的new语句

    : 发信站: 水木社区 (Fri Jun 14 01:32:53 2013), 站内

    : 这个影响太大了,很可能是 ub

    : 【 在 javaboy (喝了咖啡就话多-_-;) 的大作中提到: 】

    : : #define new int  //我闪~

    : 标  题: Re: 在代码里看到一条孤单的new语句

    : 发信站: 水木社区 (Fri Jun 14 21:53:37 2013), 站内

    : 只是标识一下,根本不是指针.你可以写一个空类看看.

    : 【 在 cppgx 的大作中提到: 】

    : : 1字节就能存个指针?这种系统还需要内存管理么。

    : :

    : --

    : 你的意思?

    : 这个不是UB啊,应该就是普通的B。。。

    : 内存管理没开销?聪明。

    : 内存管理是os的事情,和c++语言内对象大小不是一回事吧

    : class A

    : 无虚函数无成员变量

    : new A() 时会占用内存么?

    : 据说按标准 #define 关键字是 UB,不过现实中的预处理器应该都没问题

    : C++真是个蛋疼的语言,objc都比它好用

    : 好像msvc自己也在用。。类似这样的

    : #ifdef _DEBUG

    : # define new DEBUG_NEW

    : ...................

    : c++就毁在你们这种人手里,成天玩弄奇技淫巧,明明可以有很简单容易懂的方式实现的东西,非要炫技,别忘记写程序的目的是要解决问题,而不是比拼代码炫。

    2017-05-12
  • Re:群晖216J是不是压根就没法看视频?

    不是

    【 在 arsam 的大作中提到: 】

    :手机wifi联群晖,看视频卡的要命啊。手机拍的视频都要缓存半天。

    :是不是216J就这熊样?

    :...................

    2017-05-10
  • Re:请教飞机这种体验差的交通工具,为什么不被淘汰?

    你可以选择不坐啊

    【 在 negate 的大作中提到: 】

    :能不能发明更舒适的交通工具

    :即使不坠机,遇到气流也让人心惊胆战,坐着很不爽。

    :...................

    2017-05-08
  • Re: 这段代码是怎么回事

    没用到this吧

    【 在 remark (@^@ -爱伺机摸人) 的大作中提到: 】

    : struct Foo {

    :         void show(int i)

    :         {

    : ...................

    2017-05-07