IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez C++ Discussion :

Folly, la bibliothèque C++ de Facebook


Sujet :

Contribuez C++

  1. #1
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut Folly, la bibliothèque C++ de Facebook
    Folly : la bibliothèque C++ open-source de Facebook
    Une initiative pour partager les outils utilisés en interne

    Herb Sutter, l'expert reconnu du langage C++, encense dans son dernier billet de blog l'initiative de Facebook qui vient tout juste de publier en open-source sa bibliothèque d'utilités : Folly.

    Cette bibliothèque contient tout un tas d'algorithmes et de structures utilisés dans le code de Facebook. L'essentiel des fonctionnalités couvre les problèmes de performances ou d'absence d'implémentations trouvés dans les bibliothèques déjà existantes comme Boost ou la bibliothèque standard.

    De plus en plus d'entreprises mettent leur code source à disposition de tous et permettent de compléter les fonctionnalités fournies par les bibliothèques C++ disponibles. Certaines ont pour but d'être intégrées dans la bibliothèque standard C++, dans le but de corriger ce qui semble être pour Herb Sutter le problème majeur du C++ : le manque d'outils disponibles de façon standard.

    Dépôt GitHub de Folly : https://github.com/facebook/folly.

    Et vous :
    Que pensez-vous de cette initiative de Facebook ?
    Pensez-vous pouvoir utiliser cette bibliothèque dans vos propres projets ?

    Sources :

  2. #2
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Je viens de jeter en œil aux sources et il y a en effet beaucoup de choses intéressantes. Alors attention, il ne faut pas s'attendre à des bibliothèques de haut niveau genre XML, base de donnée ou réseau. Cela reste avant tout une collection de petits composants d'usage général. La majorité de ces composants sont en fait des structures de données orientées multithreading.

    Extrait du readme de Folly :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    #### `Arena.h`, `ThreadCachedArena.h`
    Simple arena for memory allocation: multiple allocations get freed all
    at once. With threaded version.
    #### [`AtomicHashMap.h`, `AtomicHashArray.h`](AtomicHashMap.md)
    High-performance atomic hash map with almost lock-free operation.
    #### [`Benchmark.h`](Benchmark.md)
    A small framework for benchmarking code. Client code registers
    benchmarks, optionally with an argument that dictates the scale of the
    benchmark (iterations, working set size etc). The framework runs
    benchmarks (subject to a command-line flag) and produces formatted
    output with timing information.
    #### `Bits.h`
    Various bit manipulation utilities optimized for speed.
    #### `Bits.h`
    Bit-twiddling functions that wrap the
    [ffsl(l)](<a href="http://linux.die.net/man/3/ffsll" target="_blank">http://linux.die.net/man/3/ffsll</a>) primitives in a uniform
    interface.
    #### `ConcurrentSkipList.h`
    An implementation of the structure described in [A Provably Correct
    Scalable Concurrent Skip
    List](<a href="http://www.cs.tau.ac.il/~shanir/nir-pubs-web/Papers/OPODIS2006-BA.pdf" target="_blank">http://www.cs.tau.ac.il/~shanir/nir-...DIS2006-BA.pdf</a>)
    by Herlihy et al.
    #### [`Conv.h`](Conv.md)
    A variety of data conversion routines (notably to and from string),
    optimized for speed and safety.
    #### `DiscriminatedPtr.h`
    Similar to `boost::variant`, but restricted to pointers only. Uses the
    highest-order unused 16 bits in a pointer as discriminator. So
    `sizeof(DiscriminatedPtr<int, string, Widget>) == sizeof(void*)`.
    #### [`dynamic.h`](Dynamic.md)
    Dynamically-typed object, created with JSON objects in mind.
    #### `Endian.h`
    Endian conversion primitives.
    ####`Escape.h`
    Escapes a string in C style.
    ####`eventfd.h`
    Wrapper around the
    [`eventfd`](<a href="http://www.kernel.org/doc/man-pages/online/pages/man2/eventfd.2.html" target="_blank">http://www.kernel.org/doc/man-pages/...eventfd.2.html</a>)
    system call.
    ####[`FBString.h`](FBString.md)
    A drop-in implementation of `std::string` with a variety of optimizations.
    ####[`FBVector.h`](FBVector.md)
    A mostly drop-in implementation of `std::vector` with a variety of
    optimizations.
    ####`Foreach.h`
    Pseudo-statements (implemented as macros) for iteration.
    ####[`Format.h`](Format.md)
    Python-style formatting utilities.
    ####[`GroupVarint.h`](GroupVarint.md)
    [Group Varint
    encoding](<a href="http://www.ir.uwaterloo.ca/book/addenda-06-index-compression.html" target="_blank">http://www.ir.uwaterloo.ca/book/adde...mpression.html</a>)
    for 32-bit values.
    ####`Hash.h`
    Various popular hash function implementations.
    ####[`Histogram.h`](Histogram.md)
    A simple class for collecting histogram data.
    ####`IntrusiveList.h`
    Convenience type definitions for using `boost::intrusive_list`.
    ####`json.h`
    JSON serializer and deserializer. Uses `dynamic.h`.
    ####`Likely.h`
    Wrappers around [`__builtin_expect`](<a href="http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html" target="_blank">http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html</a>).
    ####`Malloc.h`
    Memory allocation helpers, particularly when using jemalloc.
    ####`MapUtil.h`
    Helpers for finding items in associative containers (such as
    `std::map` and `std::unordered_map`).
    ####[`PackedSyncPtr.h`](PackedSyncPtr.md)
    A highly specialized data structure consisting of a pointer, a 1-bit
    spin lock, and a 15-bit integral, all inside one 64-bit word.
    ####`Preprocessor.h`
    Necessarily evil stuff.
    ####`PrettyPrint.h`
    Pretty-printer for numbers that appends suffixes of unit used: bytes
    (kb, MB, ...), metric suffixes (k, M, G, ...), and time (s, ms, us,
    ns, ...).
    ####[`ProducerConsumerQueue.h`](ProducerConsumerQueue.md)
    Lock free single-reader, single-writer queue.
    ####`Random.h`
    Defines only one function---`randomNumberSeed()`.
    ####`Range.h`
    Boost-style range facility and the `StringPiece` specialization.
    ####`RWSpinLock.h`
    Fast and compact reader-writer spin lock.
    ####`ScopeGuard.h`
    C++11 incarnation of the old [ScopeGuard](<a href="http://drdobbs.com/184403758" target="_blank">http://drdobbs.com/184403758</a>) idiom.
    ####[`SmallLocks.h`](SmallLocks.md)
    Very small spin locks (1 byte and 1 bit).
    ####`small_vector.h`
    Vector with the small buffer optimization and an ptional embedded
    `PicoSpinLock`.
    ####`sorted_vector_types.h`
    Collections similar to `std::map` but implemented as sorted vectors.
    ####`StlAllocator.h`
    STL allocator wrapping a simple allocate/deallocate interface.
    ####`String.h`
    String utilities that connect `folly::fbstring` with `std::string`.
    ####[`Synchronized.h`](Synchronized.md)
    High-level synchronization library.
    ####`System.h`
    Demangling and errno utilities.
    ####[`ThreadCachedInt.h`](ThreadCachedInt.md)
    High-performance atomic increment using thread caching.
    ####[`ThreadLocal.h`](ThreadLocal.md)
    Improved thread local storage for non-trivial types.
    ####`TimeoutQueue.h`
    Queue with per-item timeout.
    ####`Traits.h`
    Type traits that complement those defined in the standard C++11 header
    `<traits>`.
    ####`Unicode.h`
    Defines the `codePointToUtf8` function.
    Petite remarque, à la lecture du code j'ai été très étonné de voir que Folly propose du C++ résolument moderne.

    Par comparaison, tous les autres gros projets open source (de ma connaissance) en C++ et suffisamment massifs pour avoir eux aussi ce genre de brique de base bien fournies (par exemple llvm/clang ou chromium) ont des contraintes fortes forçant une approche assez conservative, du genre :
    - Pas d'exception
    - C++03 uniquement, souvent en bannissant certains aspects du langage pour être accepté par le plus grand nombre de compilateurs.
    - Pas de bibliothèque tierce.

    Du coup c'est assez fascinant de voir que Folly, qui si je comprends bien est la brique de base sur laquelle s’appuie tout le reste du code C++ chez Facebook, au contraire :
    - Utilise les exceptions.
    - Utilise extensivement le C++11. Il faut d'ailleurs au minimum gcc 4.6 pour compiler le code, vu l'utilisation régulière de feature comme les variadic template ou rvalue reference.
    - Utilise extensivement boost.

  3. #3
    Membre régulier
    Homme Profil pro
    Dev C/C++
    Inscrit en
    Octobre 2011
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Dev C/C++

    Informations forums :
    Inscription : Octobre 2011
    Messages : 19
    Points : 90
    Points
    90
    Par défaut
    Du coup c'est assez fascinant de voir que Folly, qui si je comprends bien est la brique de base sur laquelle s’appuie tout le reste du code C++ chez Facebook
    Le code a la marque d'Andrei Alexandrescu, qui est le guru C++ chez facebook.
    Un code de qualité, dont certain bout de code mériterais d’être envisager pour s’intégrer dans la lib standard (je pense au JSON serializer/deserializer, et aux container thread-safe, fonction de hash).

  4. #4
    Membre éclairé
    Inscrit en
    Mai 2010
    Messages
    298
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 298
    Points : 877
    Points
    877
    Par défaut
    Je me demande si HipHop peut utiliser aussi cette bibliothèque.
    "«Les petites filles sont des punks»."

  5. #5
    Membre éprouvé
    Avatar de mitkl
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2010
    Messages
    364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2010
    Messages : 364
    Points : 1 081
    Points
    1 081
    Par défaut
    Citation Envoyé par David_g Voir le message
    Je me demande si HipHop peut utiliser aussi cette bibliothèque.
    As engineers here, we use, contribute to, and release a lot of open source software, including pieces of our core infrastructure such as HipHop and Thrift.
    Si vous ne savez toujours pas ce qu’est la récursivité, relisez cette phrase.

    Mon blog sur la programmation et l'informatique !

  6. #6
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Vous êtes tombés sur des exemples d'utilisation des exceptions ? Car dans le README il est écrit que non.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  7. #7
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    J'allais le dire: dans le readme du dossier principal il est ecrit en gros qu'il est interdit d'utiliser les exceptions. Peut être que ca a changé et que ce n'est plus d'actuallité....ou alors yen a qui n'ont pas suivi les regles...

  8. #8
    Membre expérimenté Avatar de alexrtz
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2003
    Messages
    639
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juin 2003
    Messages : 639
    Points : 1 359
    Points
    1 359
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    folly/AtomicHashMap.h: *   Insert returns false if there is a key collision and throws if the max size
    folly/AtomicHashMap.h:   *   AtomicHashMapFullError is thrown.
    folly/ProducerConsumerQueue.h:      throw std::bad_alloc();
    folly/json.h: * system, the serializer will throw.
    folly/json.h:     * precisely represented by fit a double---instead, throws an
    folly/dynamic-inl.h:   * double, or throws if either is not a numeric type.
    folly/dynamic-inl.h:      throw TypeError("numeric", a.type(), b.type());
    folly/dynamic-inl.h:inline bool dynamic::isString() const { return get_nothrow<fbstring>(); }
    folly/dynamic-inl.h:inline bool dynamic::isObject() const { return get_nothrow<ObjectImpl>(); }
    folly/dynamic-inl.h:inline bool dynamic::isBool()   const { return get_nothrow<bool>(); }
    folly/dynamic-inl.h:inline bool dynamic::isArray()  const { return get_nothrow<Array>(); }
    folly/dynamic-inl.h:inline bool dynamic::isDouble() const { return get_nothrow<double>(); }
    folly/dynamic-inl.h:inline bool dynamic::isInt()    const { return get_nothrow<int64_t>(); }
    folly/dynamic-inl.h:inline bool dynamic::isNull()   const { return get_nothrow<void*>(); }
    folly/dynamic-inl.h:    throw TypeError("object", type_);
    folly/dynamic-inl.h:      throw TypeError("int64", type(), o.type());           \
    folly/dynamic-inl.h:    throw TypeError("object/array", type());
    folly/dynamic-inl.h:    throw TypeError("object/array", type());
    folly/dynamic-inl.h:  if (auto* parray = get_nothrow<Array>()) {
    folly/dynamic-inl.h:      throw std::out_of_range("out of range in dynamic array");
    folly/dynamic-inl.h:      throw TypeError("int64", idx.type());
    folly/dynamic-inl.h:  auto* pobj = get_nothrow<ObjectImpl>();
    folly/dynamic-inl.h:    throw std::out_of_range(to<std::string>(
    folly/dynamic-inl.h:  if (auto* ar = get_nothrow<Array>()) {
    folly/dynamic-inl.h:  if (auto* obj = get_nothrow<ObjectImpl>()) {
    folly/dynamic-inl.h:  if (auto* str = get_nothrow<fbstring>()) {
    folly/dynamic-inl.h:  throw TypeError("array/object", type());
    folly/dynamic-inl.h:    throw TypeError("not null/object/array", type());
    folly/dynamic-inl.h:  case INT64:    return to<T>(*get_nothrow<int64_t>());
    folly/dynamic-inl.h:  case DOUBLE:   return to<T>(*get_nothrow<double>());
    folly/dynamic-inl.h:  case BOOL:     return to<T>(*get_nothrow<bool>());
    folly/dynamic-inl.h:  case STRING:   return to<T>(*get_nothrow<fbstring>());
    folly/dynamic-inl.h:    throw TypeError("int/double/bool/string", type());
    folly/dynamic-inl.h:T* dynamic::get_nothrow() {
    folly/dynamic-inl.h:T const* dynamic::get_nothrow() const {
    folly/dynamic-inl.h:  return const_cast<dynamic*>(this)->get_nothrow<T>();
    folly/dynamic-inl.h:  if (auto* p = get_nothrow<T>()) {
    folly/dynamic-inl.h:  throw TypeError(TypeInfo<T>::name, type());
    folly/docs/Dynamic.md:`folly::TypeError`. Other exceptions can also be thrown if
    folly/docs/Dynamic.md:    dynamic hugeDoub = hugeInt.asDouble();  // throws a folly/Conv.h error,
    folly/docs/Conv.md:* Otherwise, `to` inserts bounds checks and throws
    folly/docs/FBVector.md:assignment is the same as bitblitting the bits over) or a nothrow
    folly/docs/FBVector.md:      (boost::has_trivial_assign<T>::value || boost::has_nothrow_constructor<T>::value));
    folly/FormatArg.h:   * Validate the argument for the given type; throws on error.
    folly/FormatArg.h:   * is thrown otherwise).
    folly/FormatArg.h:   * integer (an exception is thrown otherwise).
    folly/FormatArg.h:  throw std::invalid_argument(to<std::string>(
    folly/Conv.h:  ((condition) ? (void)0 : throw std::range_error(                      \
    folly/Conv.h: * in which case digits_to throws.
    folly/Conv.h:    throw std::range_error("Cannot convert string " +
    folly/Conv.h:      throw std::range_error("Unable to convert an empty string"
    folly/Conv.h:  throw std::range_error("Unable to convert \"" + src->toString()
    folly/Conv.h:    throw std::range_error(
    folly/sorted_vector_types.h:  // Nothrow as long as swap() on the Compare type is nothrow.
    folly/sorted_vector_types.h:  // Nothrow as long as swap() on the Compare type is nothrow.
    folly/test/DiscriminatedPtrTest.cpp:  EXPECT_EQ(&a, p.get_nothrow<int>());
    folly/test/DiscriminatedPtrTest.cpp:  EXPECT_EQ(&a, static_cast<const Ptr&>(p).get_nothrow<int>());
    folly/test/DiscriminatedPtrTest.cpp:  EXPECT_EQ(static_cast<void*>(NULL), p.get_nothrow<void>());
    folly/test/DiscriminatedPtrTest.cpp:  EXPECT_EQ(static_cast<int*>(NULL), p.get_nothrow<int>());
    folly/test/ScopeGuardTest.cpp:      throw std::runtime_error("destructors should never throw!");
    folly/test/ScopeGuardTest.cpp:  "destructors should never throw");
    folly/test/ScopeGuardTest.cpp: * to close a db connection regardless if an exception was thrown during
    folly/test/ScopeGuardTest.cpp: *     throw e; // re-throw the exception
    folly/test/ScopeGuardTest.cpp:        throw std::runtime_error("throwing an expected error");
    folly/test/ScopeGuardTest.cpp:        throw "never throw raw strings";
    folly/test/ScopeGuardTest.cpp:    throw std::runtime_error("test");
    folly/test/FBStringLibstdcxxStdexceptTest.cpp:          (use std::__throw_* from funcexcept.h instead)
    folly/test/ConvTest.cpp:  // However, if the next character would cause an overflow it throws a
    folly/test/ConvTest.cpp:    throw std::runtime_error("empty string");
    folly/test/ConvTest.cpp:      throw std::runtime_error("overflow");
    folly/test/ConvTest.cpp:    throw std::runtime_error("extra chars at the end");
    folly/test/AtomicHashMapTest.cpp:    static bool throwException_ = false;
    folly/test/AtomicHashMapTest.cpp:    throwException_ = !throwException_;
    folly/test/AtomicHashMapTest.cpp:    if (throwException_) {
    folly/test/AtomicHashMapTest.cpp:      throw 1;
    folly/test/small_vector_test.cpp:int throwCounter = 1;
    folly/test/small_vector_test.cpp:  if (!--throwCounter) {
    folly/test/small_vector_test.cpp:    throw TestException();
    folly/test/small_vector_test.cpp:// Check that throws don't break the basic guarantee for some cases.
    folly/test/small_vector_test.cpp:// throwing code paths to occur.
    folly/test/small_vector_test.cpp:    throwCounter = 1000;
    folly/test/small_vector_test.cpp:    throwCounter = 1000;
    folly/test/small_vector_test.cpp:      throwCounter = 1000;
    folly/test/small_vector_test.cpp:      throwCounter = counter;
    folly/test/small_vector_test.cpp:       * of the above push_back's, and one of the Throwers throws,
    folly/test/small_vector_test.cpp:    throwCounter = 4;
    folly/StlAllocator.h: * alignment required on your system), throwing std::bad_alloc if the
    folly/StlAllocator.h: *     if (!p) throw std::bad_alloc();
    folly/dynamic.h: * complete interface than the raw type), and it'll just throw a
    folly/dynamic.h:   * those types.  For objects, we throw TypeError.
    folly/dynamic.h:   * These throw TypeError when used with types or type combinations
    folly/dynamic.h:   * These functions may also throw if you use 64-bit integers with
    folly/dynamic.h:   * throws TypeError.
    folly/dynamic.h:   * non-arrays will throw a TypeError.
    folly/dynamic.h:   * value) in an object.  Calling these on non-objects will throw a TypeError.
    folly/dynamic.h:   * the given name.  Otherwise throws TypeError.
    folly/dynamic.h:   * will throw a TypeError.  Using an index that is out of range or
    folly/dynamic.h:   * object-element that's not present throws std::out_of_range.
    folly/dynamic.h:   * In the case of an array, the index must be an integer, and this will throw
    folly/dynamic.h:   * value if the key isn't present.  The const overload will throw
    folly/dynamic.h:   * Only defined for objects, throws TypeError otherwise.
    folly/dynamic.h:   * Inserts the supplied key-value pair to an object, or throws if
    folly/dynamic.h:   * Append elements to an array.  If this is not an array, throws
    folly/dynamic.h:  template<class T> T*       get_nothrow();
    folly/dynamic.h:  template<class T> T const* get_nothrow() const;
    folly/String.h: * In strict mode (default), throws std::invalid_argument if it encounters
    folly/String.h: * This function may allocate memory (and therefore throw).
    folly/String.h:struct has_nothrow_constructor<folly::basic_fbstring<T> > : true_type {
    folly/DiscriminatedPtr.h: * throws an exception (and get_nothrow returns nullptr)
    folly/DiscriminatedPtr.h:  T* get_nothrow() noexcept {
    folly/DiscriminatedPtr.h:  const T* get_nothrow() const noexcept {
    folly/DiscriminatedPtr.h:   * Types), and throws std::invalid_argument if this DiscriminatedPtr is empty
    folly/DiscriminatedPtr.h:      throw std::invalid_argument("Invalid type");
    folly/DiscriminatedPtr.h:      throw std::invalid_argument("Invalid type");
    folly/DiscriminatedPtr.h:    if (n == 0) throw std::invalid_argument("Empty DiscriminatedPtr");
    folly/DiscriminatedPtr.h:    if (n == 0) throw std::invalid_argument("Empty DiscriminatedPtr");
    folly/Format-inl.h:  // and throw if we see any lone "}"
    folly/Format-inl.h:        throw std::invalid_argument(
    folly/Format-inl.h:      throw std::invalid_argument(
    folly/Format-inl.h:      throw std::invalid_argument("folly::format: missing ending '}'");
    folly/Format-inl.h:      throw std::invalid_argument(
    folly/String-inl.h:        throw std::invalid_argument("incomplete escape sequence");
    folly/String-inl.h:          throw std::invalid_argument("incomplete hex escape sequence");
    folly/String-inl.h:        throw std::invalid_argument("invalid escape sequence");
    folly/small_vector.h: * overflow the in situ capacity we throw an exception.
    folly/small_vector.h:      // threw: if someone throws from a move constructor the effects
    folly/small_vector.h:      throw;
    folly/small_vector.h:      throw;
    folly/small_vector.h:   * anything throws, undo what we did.
    folly/small_vector.h:      throw;
    folly/small_vector.h:   * Basic guarantee only.  Provides the nothrow guarantee iff our
    folly/small_vector.h:   * value_type has a nothrow move or copy constructor.
    folly/small_vector.h:        throw;
    folly/small_vector.h:      throw;
    folly/small_vector.h:     * constructor throwing by clearing the whole vector).
    folly/small_vector.h:     * constructor throws, you either need a nothrow default
    folly/small_vector.h:     * constructor or a nothrow copy/move to get something back in the
    folly/small_vector.h:      throw std::out_of_range();
    folly/small_vector.h:      throw std::out_of_range();
    folly/small_vector.h:   * objects and insertion outside the function, otherwise exception is thrown.
    folly/small_vector.h:      throw std::length_error("max_size exceeded in small_vector");
    folly/small_vector.h:      throw std::bad_alloc();
    folly/small_vector.h:        throw;
    folly/small_vector.h:        throw;
    folly/small_vector.h:        throw;
    folly/small_vector.h:        throw;
    folly/small_vector.h:// Basic guarantee only, or provides the nothrow guarantee iff T has a
    folly/small_vector.h:// nothrow move or copy constructor.
    folly/experimental/TestUtil.cpp:    throw std::system_error(errno, std::system_category(),
    folly/experimental/TestUtil.cpp:      throw std::system_error(errno, std::system_category(),
    folly/experimental/io/Cursor.h:      throw std::out_of_range("underflow");
    folly/experimental/io/Cursor.h:      throw std::out_of_range("underflow");
    folly/experimental/io/Cursor.h:      throw std::out_of_range("overflow");
    folly/experimental/io/Cursor.h: * (and push() and ensure() will throw) if growth == 0.
    folly/experimental/io/Cursor.h:      throw std::out_of_range("can't grow buffer chain");
    folly/experimental/io/IOBuf.h:   * second argument.  The free function must never throw exceptions.
    folly/experimental/io/IOBuf.h:   * On error, std::bad_alloc will be thrown.  If freeOnError is true (the
    folly/experimental/io/IOBuf.h:   * default) the buffer will be freed before throwing the error.
    folly/experimental/io/IOBuf.h:   * On error, std::bad_alloc will be thrown.
    folly/experimental/io/IOBuf.h:   * Currently unshare may also throw std::overflow_error if it tries to
    folly/experimental/io/IOBuf.cpp:    throw std::bad_alloc();
    folly/experimental/io/IOBuf.cpp:      throw std::bad_alloc();
    folly/experimental/io/IOBuf.cpp:    throw;
    folly/experimental/io/IOBuf.cpp:          // The user's free function is not allowed to throw.
    folly/experimental/io/IOBuf.cpp:    throw;
    folly/experimental/io/IOBuf.cpp:    throw std::overflow_error("IOBuf chain too large to coalesce");
    folly/experimental/io/IOBuf.cpp:      // The user's free function should never throw.  Otherwise we might
    folly/experimental/io/IOBuf.cpp:      // throw from the IOBuf destructor.  Other code paths like coalesce()
    folly/experimental/io/IOBuf.cpp:      // also assume that decrementRefcount() cannot throw.
    folly/experimental/io/IOBuf.cpp:            throw std::bad_alloc();
    folly/experimental/io/IOBuf.cpp:          throw std::bad_alloc();
    folly/experimental/io/IOBuf.cpp:      throw std::bad_alloc();
    folly/experimental/io/IOBuf.cpp:    throw std::bad_alloc();
    folly/experimental/io/IOBufQueue.h:   * @throws std::underflow_error if n exceeds the number of bytes
    folly/experimental/io/IOBufQueue.h:      throw std::invalid_argument("IOBufQueue: chain length not cached");
    folly/experimental/io/IOBufQueue.cpp:      throw std::underflow_error(
    folly/experimental/io/IOBufQueue.cpp:      throw std::underflow_error(
    folly/experimental/io/IOBufQueue.cpp:      throw std::underflow_error(
    folly/Traits.h:  struct has_nothrow_constructor<  __VA_ARGS__ > : ::boost::true_type {};
    folly/Traits.h: * above, and that it has a nothrow constructor. Most types can be
    folly/Traits.h:struct has_nothrow_constructor< std::pair<T, U> >
    folly/Traits.h:    : ::boost::mpl::and_< has_nothrow_constructor<T>,
    folly/Traits.h:                          has_nothrow_constructor<U> > {};
    folly/Range.h:    if (i >= size()) throw std::out_of_range("index out of range");
    folly/Range.h:    if (i >= size()) throw std::out_of_range("index out of range");
    folly/FBVector.h:  boost::has_nothrow_constructor<T>::value
    folly/FBVector.h:  !boost::has_nothrow_constructor<T>::value
    folly/FBVector.h: * value. If the operation throws, destroys all objects constructed so
    folly/FBVector.h:  } else if (boost::has_nothrow_constructor<T>::value) {
    folly/FBVector.h:      throw;
    folly/FBVector.h: * operation throws, destroys all objects constructed so far and calls
    folly/FBVector.h:      throw;
    folly/FBVector.h:      // Careful here, fill and uninitialized_fill may throw. The
    folly/FBVector.h:      throw std::out_of_range("fbvector: index is greater than size.");
    folly/FBVector.h:        throw;
    folly/FBVector.h:        throw;
    folly/FBString.h:      void (*throw_exc)(const char*),
    folly/FBString.h:    if (!condition) throw_exc(msg);
    folly/FBString.h:          std::__throw_logic_error(err.c_str());
    folly/FBString.h:    enforce(res_arg <= max_size(), std::__throw_length_error, "");
    folly/FBString.h:    enforce(n <= size(), std::__throw_out_of_range, "");
    folly/FBString.h:    enforce(n < size(), std::__throw_out_of_range, "");
    folly/FBString.h:    enforce(pos <= sz, std::__throw_out_of_range, "");
    folly/FBString.h:    enforce(pos <= sz, std::__throw_out_of_range, "");
    folly/FBString.h:    enforce(pos2 <= str.length(), std::__throw_out_of_range, "");
    folly/FBString.h:    enforce(pos <= length(), std::__throw_out_of_range, "");
    folly/FBString.h:    enforce(pos <= length(), std::__throw_out_of_range, "");
    folly/FBString.h:    enforce(pos <= length(), std::__throw_out_of_range, "");
    folly/FBString.h:    enforce(pos <= size(), std::__throw_out_of_range, "");
    folly/FBString.h:    enforce(pos2 <= str.length(), std::__throw_out_of_range, "");
    folly/FBString.h:    enforce(pos <= size(), std::__throw_out_of_range, "");
    folly/FBString.h:    enforce(pos <= size(), std::__throw_out_of_range, "");
    folly/FBString.h:    enforce(pos <= size(), std::__throw_out_of_range, "");
    folly/FBString.h:    enforce(pos1 <= size(), std::__throw_out_of_range, "");
    folly/FBString.h:    enforce(pos2 <= str.size(), std::__throw_out_of_range, "");
    folly/detail/ThreadLocalDetail.h:      throw std::runtime_error("pthread_key_create failed: " + msg);
    folly/detail/ThreadLocalDetail.h:      LOG(WARNING) << "Destructor discarding an exception that was thrown.";
    folly/detail/ThreadLocalDetail.h:          throw std::bad_alloc();
    folly/AtomicHashMap-inl.h:    throw AtomicHashMapFullError();
    folly/AtomicHashArray-inl.h:            throw;
    folly/ScopeGuard.h: *   // this will throw an exception upon error, which
    folly/ScopeGuard.h: *   // an exception was not thrown, so don't execute
    folly/String.cpp:    throw std::runtime_error(
    folly/String.cpp:      throw std::runtime_error(
    folly/json.cpp:    throw std::runtime_error("folly::decodeUtf8 empty/invalid string");
    folly/json.cpp:    throw std::runtime_error(
    folly/json.cpp:      throw std::runtime_error(
    folly/json.cpp:        throw std::runtime_error(
    folly/json.cpp:          throw std::runtime_error(
    folly/json.cpp:  throw std::runtime_error("folly::decodeUtf8 encoding length maxed out");
    folly/json.cpp:      throw std::runtime_error("folly::toJson: JSON object key was not a "
    folly/json.cpp:      throw ParseError(lineNum_, context(),
    folly/json.cpp:    throw ParseError(lineNum_, context(), what);
    folly/Arena.h: *      alignment required on your system; throw std::bad_alloc if the
    folly/Arena.h:    if (!mem) throw std::bad_alloc();
    "Je suis incapable d'expliquer ce qui se passa ensuite : je lâchai quelque chose, quelque chose à quoi je m'agrippais depuis toujours sans m'en rendre compte. Je m'enfonçais dans une obscurité chaude, moelleuse et protectrice, tandis qu'un loup montait la garde par mes propres yeux."

  9. #9
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Merci, je viens de rajouter l'info dans ma réponse là: http://programmers.stackexchange.com.../113481#113481

  10. #10
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Oui c'est vraiment curieux ce désaccord dans Folly entre doc et code.
    Le code actuel utilise assez régulièrement les exceptions. On en trouve parfois jusque dans les briques vraiment basique comme fbvector et small_vector (std::out_of_range, std::length_error, std::bad_alloc etc.). Il y a aussi régulièrement des commentaires indiquant le degré d'exception safety de certaines fonctions. Autre exemple, la biliothèque json qui utilise systématiquement les exceptions pour remonter les erreurs de parsing (std::runtime_error(to<std::string>("json parse error on line ", line))

    Klaim :
    Pour ta réponse sur stackoverflow, un autre exemple célèbre de compagnie bannissant les exceptions en bloc pour la totalité de leur code C++ : google
    http://google-styleguide.googlecode....xml#Exceptions
    (intéressant car contient de nombreuses justifications)

  11. #11
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    google est dans un des rares cas où c'est correctement justifié : base de vieux code trop importante pour initier une migration comme ça.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  12. #12
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Posté sur la mailing list de boost :
    https://www.facebook.com/notes/faceb...50864656793920

    I'm Tudor, one of the folly developers. I'll try to answer your questions
    or poke the appropriate people

    Re: "NO EXCEPTIONS" in the README -- the README file was intended for
    internal Facebook contributors (hence stray references to internal paths),
    and "NO EXCEPTIONS" referred to "no exceptions to the rules above", NOT "no
    C++ exceptions". Will fix / clarify / remove soon.

    -Tudor.
    Donc les exceptions C++ sont autorisées !

    Remarque @Klaim : Dans http://programmers.stackexchange.com.../113481#113481 je ne suis pas d'accord avec toute une série d'arguments qui vont tous dans le sens : De toute façon, une exception, c'est juste des infos de crash plus jolies, mais nous, on n'a pas le droit de crasher (et on a des environnements qui nous permettent de ne pas le faire). C'est typiquement l'argument contre une fonctionnalité de quelqu'un qui ne l'a pas utilisée pour de vrai. Une exception n'est pas un crash. C'est un mécanisme de remontées d'erreurs comme un autre, qui comme un autre peut conduire au traitement silencieux de celles-ci, ou à la fin du programme, ou à un tas d'intermédiaires, mais uniquement selon le code de gestion des erreurs, qui lui est indépendant de la technique de remontée utilisée.

    Je ne nie pas l’argument performances (ni ne l'admets, je n'ai juste pas assez d'infos là dessus). Mais j'accepterais que les jeux n'ont aucun intérêt à utiliser un mécanisme d'exception le jour où on me justifiera que les jeux n'ont pas non plus de mécanisme de code de retour de fonction indiquant si la fonction s'est finie avec succès ou pas.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  13. #13
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Posté sur la mailing list de boost :

    Donc les exceptions C++ sont autorisées !
    Ah, devancé


    Remarque @Klaim : Dans http://programmers.stackexchange.com.../113481#113481 je ne suis pas d'accord avec toute une série d'arguments qui vont tous dans le sens : De toute façon, une exception, c'est juste des infos de crash plus jolies, mais nous, on n'a pas le droit de crasher (et on a des environnements qui nous permettent de ne pas le faire). C'est typiquement l'argument contre une fonctionnalité de quelqu'un qui ne l'a pas utilisée pour de vrai. Une exception n'est pas un crash. C'est un mécanisme de remontées d'erreurs comme un autre, qui comme un autre peut conduire au traitement silencieux de celles-ci, ou à la fin du programme, ou à un tas d'intermédiaires, mais uniquement selon le code de gestion des erreurs, qui lui est indépendant de la technique de remontée utilisée.

    Je ne nie pas l’argument performances (ni ne l'admets, je n'ai juste pas assez d'infos là dessus). Mais j'accepterais que les jeux n'ont aucun intérêt à utiliser un mécanisme d'exception le jour où on me justifiera que les jeux n'ont pas non plus de mécanisme de code de retour de fonction indiquant si la fonction s'est finie avec succès ou pas.

    Et je suis tout a fait d'accord! (voir les commentaires a ce sujet). Personellement, jusqu'a ce que j'ai des contraintes fortes, je prefere de loin avoir les exceptions activées quand je bosse sur des jeux. Parfois je n'ai pas le choix, mais heureusement ça deviens (pour moi) de plus en plus rare.

    Comme je le dis dans ma réponse, ce sont les arguments apportés, pas les miens mais ceux qui sont constamment ressassés.
    Le problème de performance est toutefois important une fois qu'on fait un blockbuster bien gourmand mais sinon il n'a pas lieu d'être un probleme.

  14. #14
    Membre éclairé
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Points : 879
    Points
    879
    Par défaut
    Sauf que, comme le fait remarquer un des articles qui est en traduction (je crois), les exceptions sont souvent moins gourmandes en ressources que l'utilisation d'un code de retour. En tout cas, tant qu'elles restent exceptionnelles, bien sûr. Mais, si il y a autant d'erreurs que de retours normaux, est-ce toujours une erreur ?

  15. #15
    Membre émérite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    832
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 832
    Points : 2 625
    Points
    2 625
    Par défaut
    La consommation en ressources du traitement des exceptions varie selon le compilateur, donc il est difficile d'affirmer de façon catégorique que ça pèse vraiment lourd.
    Et, naturellement, j'ai ici parlé de ressources de façon générale.
    Selon mes lectures en survol à ce sujet, il y a grosso modo deux stratégies pour les gérer:
    _ augmenter la taille du code
    _ augmenter les traitements processeur

    Avec GCC, selon la doc, une exception n'a un coût que si elle est lancée, mais le binaire augmente un peu.
    Honnêtement... J'aime beaucoup l'optimisation, mais je préfère un programme qui ne crash pas, et qui ne contiens pas de memory leak.
    Donc, j'aime bien les contrôles d'erreur.
    Si on veut me dire que les exceptions consomment, je veux voir un comparatif, entre un source C et un C++, ou chaque fonction du C retourne un code erreur, et ou celui-ci est systématiquement vérifié.
    Ca inclut printf/scanf, naturellement...

    Si il s'avère que le binaire C résultant d'un tel code est plus rapide, plus petit en RAM, plus petit sur le disque, et plus lisible, alors je serai conquis. (En fait, même juste la moitié de ces arguments commencerait à me faire réfléchir... mais bon, je doute qu'un code sans exception vérifie toutes les conditions d'erreurs. Déjà qu'avec les exceptions ce n'est pas toujours le cas...)

    Sauf que:
    _ coller des if partout dans le code augmente la taille du binaire, même si ce ne sont que 3 octets par occurrence pour un short jump (selon mes souvenirs d'asm)
    _ coller des if partout dans le code implique des vérifications. Et chaque vérification consomme du temps processeur. J'imagine une fonction récursive qui à été appelée 50 fois... et j'ai un sérieux doute quand à la légèreté des vérifs de retour d'erreur classique.
    _ "accessoirement" mélanger le code de traitement d'erreur avec le code d'exécution normal, ça rend le code illisible.

    Bon, après, c'est vrai aussi, il semble qu'il est possible de bricoler un système pas trop mal en C avec signal.h et les longjump, mais je n'en ai pas encore vu, moi.
    Je pense que les exceptions, c'est un peu comme l'orienté objet: quelque chose dont tout le monde parle mais qui est moins répandu qu'on ne voudrait le croire.
    En tout cas, je n'en ai pas vu à mon taf actuel, ni sur les 2-3 projets open source que j'ai osé vouloir lire. (Ni l'un ni l'autre d'ailleurs: ni exceptions, ni conception orientée objet, alors que les langages le permettent...)

  16. #16
    Membre éclairé
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Points : 879
    Points
    879
    Par défaut
    Citation Envoyé par Freem Voir le message
    La consommation en ressources du traitement des exceptions varie selon le compilateur, donc il est difficile d'affirmer de façon catégorique que ça pèse vraiment lourd.
    Et, naturellement, j'ai ici parlé de ressources de façon générale.
    Selon mes lectures en survol à ce sujet, il y a grosso modo deux stratégies pour les gérer:
    _ augmenter la taille du code
    _ augmenter les traitements processeur
    Augmenter la taille du code => Oui mais non.
    Soit il y a setjmp / longjmp ; qui génèrent des points de saut pour gérer les exceptions. Méthode qui n'est quasiment plus utilisée, car elle n'est efficace que dans le cas d'une exception très fréquente. Mais, il me semble qu'il y a des options pour la réactiver sur certains compilateurs.
    Soit il y a la exception handling table (pas sûr du nom). En gros, lorsqu'on lance une exception, on va voir la table et on en tire les choses à faire. Ca alourdit un peu l'exécutable, mais ... Par rapport à tous les opcodes de jz +X ret (voire plus d'opcodes encode), je ne suis pas certain que ça augmente la taille du code par rapport à un code de gestion d'erreurs manuelle.

    Citation Envoyé par Freem
    Avec GCC, selon la doc, une exception n'a un coût que si elle est lancée, mais le binaire augmente un peu.
    Honnêtement... J'aime beaucoup l'optimisation, mais je préfère un programme qui ne crash pas, et qui ne contiens pas de memory leak.
    Donc, j'aime bien les contrôles d'erreur.
    => ?
    Là, je ne comprense pas.
    C'est de l'humour, peut-être ?
    Parce que, au moins, avec une exception on crash proprement (destructeurs, etc.).
    Avec un code de contrôle d'erreur de retour dans lequel on oublie ne serait-ce qu'une erreur possible (après tout, il suffit d'oublier un if, c'est tellement fréquent), on va d'abord tout exploser en continuant l'exécution d'un code dont les préconditions ne sont pas respectées, et ensuite on va crasher. Avec donc un risque de corruption du reste du système (fs, sauvegarde,...) beaucoup plus grand.

    Citation Envoyé par Freem
    Si on veut me dire que les exceptions consomment, je veux voir un comparatif, entre un source C et un C++, ou chaque fonction du C retourne un code erreur, et ou celui-ci est systématiquement vérifié.
    Ca inclut printf/scanf, naturellement...

    Si il s'avère que le binaire C résultant d'un tel code est plus rapide, plus petit en RAM, plus petit sur le disque, et plus lisible, alors je serai conquis. (En fait, même juste la moitié de ces arguments commencerait à me faire réfléchir... mais bon, je doute qu'un code sans exception vérifie toutes les conditions d'erreurs. Déjà qu'avec les exceptions ce n'est pas toujours le cas...)
    Comment oublier de gérer une exception ?
    Dans tous les cas, le binaire sera plus lent (plus de sauts conditionnels), à peu près aussi grand en RAM (opcodes supplémentaires vs. table d'exceptions), aussi grand sur le disque (idem), et moins lisible (nécessité de vérifier le code de retour même avec du SBRM) ...

    Citation Envoyé par Freem
    Sauf que:
    _ coller des if partout dans le code augmente la taille du binaire, même si ce ne sont que 3 octets par occurrence pour un short jump (selon mes souvenirs d'asm)
    _ coller des if partout dans le code implique des vérifications. Et chaque vérification consomme du temps processeur. J'imagine une fonction récursive qui à été appelée 50 fois... et j'ai un sérieux doute quand à la légèreté des vérifs de retour d'erreur classique.
    _ "accessoirement" mélanger le code de traitement d'erreur avec le code d'exécution normal, ça rend le code illisible.

    Bon, après, c'est vrai aussi, il semble qu'il est possible de bricoler un système pas trop mal en C avec signal.h et les longjump, mais je n'en ai pas encore vu, moi.
    Je pense que les exceptions, c'est un peu comme l'orienté objet: quelque chose dont tout le monde parle mais qui est moins répandu qu'on ne voudrait le croire.
    En tout cas, je n'en ai pas vu à mon taf actuel, ni sur les 2-3 projets open source que j'ai osé vouloir lire. (Ni l'un ni l'autre d'ailleurs: ni exceptions, ni conception orientée objet, alors que les langages le permettent...)
    En bref, un énorme +1.

  17. #17
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Ce que beaucoup oublient avec l'argument des ifs a la place des exceptions, c'est que le choix de ne pas utiliser d'exceptions n'implique pas que l'on va checker les erreurs. C'est ce qui se passe dans beaucoup de jeux vidéos: on met beaucoup beaucoup d'assertions pour crasher le plus vite possible pendant le développement ou au moins logger et puis continuer, mais une fois que le jeu est suffisamment prêt on vire tout et il n'y a aucune vérification d'erreur. Une des raisons qui rends cela possible est tout simplement qu'un jeu console n'a que des inputs fixes et prévisibles, du coup il est possible de se retrouver, après beaucoup de travail, avec un jeu qui
    tourne "parfaitement" sans aucune vérification du tout.

    Cela étant dis, hors du contexte d'un jeu console, pour une console des anciennes générations du moins, cet argument ne tiens plus.

    Pour le point sur l'activation des exceptions: en théorie on est censé ne pas payer si il n'y a aucun throw de fait. Dans la pratique on paye mémé dans ce cas. Par contre, aujourd’hui sur la plupart des plateformes (mais pas sur console ou sur la plupart des systèmes embarques, pas les smartphones) le cout est très faible donc ça va encore. Sur certaines consoles comme la DS le simple fait qu'il n'y ai que 4mo de mémoire virtuelle "normale" a laquelle on doit imputer la taille de l’exécutable fais que le coût du mécanisme d'exception en terme de taille d’exécutable n'est pas du tout acceptable. Je ne sais pas pour la 3ds qui a sacrement beaucoup plus de mémoire, mais j’imagine qu'il y a des contraintes similaires parce que c'est pas non plus un pc ou même un smartphone.

  18. #18
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Ouais enfin. Il y a erreur alors.
    Si le code peut utiliser des assert plutôt que des if dans tous les sens, cela signifie que les éventuelles erreurs trouvées sont des erreurs de programmation et non de problèmes dans le contexte de l'exécution (comme une connexion réseau à internet perdue).

    Les exceptions n'ont pas leur place. Pas plus que les if. C'est des assertions qu'il faut, et le débat exception ou pas n'a pas lieu d'être pour ces "erreurs là".
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  19. #19
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Oui mais la encore il y a subtilité.

    Quel est l'effet d'une assertion? Log + crash souvent.

    Mais pour un jeu ça peut etre problématique. Une série d'assertions peuvent donner plus d'indices sur l'ampleur d'un probleme qu'une seule assertion qui fait tout crasher.

    Du coup beaucoup d'assertions sont implémentées pour logger et etre evaluable optionellement, pour quand meme generer du code dans le cas ou l'assertion ne passe pas OU pour crasher OU pour lancer une exception.
    En plus les assertions sont rarement gardées dans le code d'un jeu, ils sont utilisés seulement dans des versions "debug" ou "release debug" du jeu, pour des soucis de performances.

    Du coup exceptions, tests unitaires et assertions devraient marcher mains dans la mains, mais devraient être desactivable si besoin.

    Enfin bref, ce que je veux dire c'est que comprendre l'ampleur et du sujet mais aussi comprendre que les termes employés ont tendance à englober trop de choses qui ne sont pas forcément sous entendues par toutes les parties de la discussion, fait que les discussions tournent rapidement steriles sur le sujet...

  20. #20
    Membre éclairé
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Points : 879
    Points
    879
    Par défaut
    Citation Envoyé par Klaim Voir le message
    Ce que beaucoup oublient avec l'argument des ifs a la place des exceptions, c'est que le choix de ne pas utiliser d'exceptions n'implique pas que l'on va checker les erreurs. C'est ce qui se passe dans beaucoup de jeux vidéos: on met beaucoup beaucoup d'assertions pour crasher le plus vite possible pendant le développement ou au moins logger et puis continuer, mais une fois que le jeu est suffisamment prêt on vire tout et il n'y a aucune vérification d'erreur. Une des raisons qui rends cela possible est tout simplement qu'un jeu console n'a que des inputs fixes et prévisibles, du coup il est possible de se retrouver, après beaucoup de travail, avec un jeu qui
    tourne "parfaitement" sans aucune vérification du tout.
    Auquel cas, un équivalent exceptions qui permet de conserver la remontée de pile automatique (bien sûr, si on ne cherche de travail que pour les assertions ça ne servira à rien, mais bon...) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #define THROW(...) throw __VA_ARGS__
    #define TRY(...) try { __VA_ARGS__ }
    #define CATCH_EXPAND(...) __VA_ARGS__
    #define CATCH(T, ...) catch(CATCH_EXPAND T) { __VA_ARGS__ }
    // Bien sûr, en release, on supprime tous les rhs
     
    // Usage :
    TRY (
      // Code normal, comme si try { }
      THROW(some::exception<a, b, c>(abc));
      // etc.
    ) CATCH ((some::exception<a, b, c> const & e),
      // Code de gestion d'erreur)
    )
    Après, j'avoue en voir mal l'intérêt.

    Cela étant dis, hors du contexte d'un jeu console, pour une console des anciennes générations du moins, cet argument ne tiens plus.

    Pour le point sur l'activation des exceptions: en théorie on est censé ne pas payer si il n'y a aucun throw de fait. Dans la pratique on paye mémé dans ce cas. Par contre, aujourd’hui sur la plupart des plateformes (mais pas sur console ou sur la plupart des systèmes embarques, pas les smartphones) le cout est très faible donc ça va encore. Sur certaines consoles comme la DS le simple fait qu'il n'y ai que 4mo de mémoire virtuelle "normale" a laquelle on doit imputer la taille de l’exécutable fais que le coût du mécanisme d'exception en terme de taille d’exécutable n'est pas du tout acceptable. Je ne sais pas pour la 3ds qui a sacrement beaucoup plus de mémoire, mais j’imagine qu'il y a des contraintes similaires parce que c'est pas non plus un pc ou même un smartphone.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    #include <iostream>
     
    #define C 0x42424242
     
    int f(int i) {
       if (i == C + 1) {
    #ifdef WITH_EXC
          throw "some exception";
    #else
          return 0x42;
    #endif
       }
       return i - C;
    }
     
    int main() {
       int i;
       std::cin >> i;
       i += C;
    #ifdef WITH_EXC
       try {
          return f(i);
       } catch(...) {
          return 1;
       }
    #else
       return f(i);
    #endif
    }
    Compilé avec WITH_EXC, g++ triche : il inline. Mais on peut décemment supposer que les fonctions méritant des exceptions ne seront, théoriquement, pas inlinées.

    Sans WITH_EXC :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    (gdb) disas main
    Dump of assembler code for function main:
       0x0000000000400810 <+0>:     sub    rsp,0x18
       0x0000000000400814 <+4>:     mov    edi,0x600e60
       0x0000000000400819 <+9>:     lea    rsi,[rsp+0xc]
       0x000000000040081e <+14>:    call   0x4007c0 <_ZNSirsERi@plt>
       0x0000000000400823 <+19>:    mov    edi,DWORD PTR [rsp+0xc]
       0x0000000000400827 <+23>:    add    edi,0x42424242
       0x000000000040082d <+29>:    mov    DWORD PTR [rsp+0xc],edi
       0x0000000000400831 <+33>:    call   0x400980 <_Z1fi>
       0x0000000000400836 <+38>:    add    rsp,0x18
       0x000000000040083a <+42>:    ret    
       0x000000000040083b <+43>:    mov    rdi,rax
       0x000000000040083e <+46>:    call   0x4007f0 <__cxa_begin_catch@plt>
       0x0000000000400843 <+51>:    call   0x4007e0 <__cxa_end_catch@plt>
       0x0000000000400848 <+56>:    mov    eax,0x1
       0x000000000040084d <+61>:    jmp    0x400836 <main+38>
    End of assembler dump.
    (gdb) disas f
    Dump of assembler code for function _Z1fi:
       0x0000000000400980 <+0>:     cmp    edi,0x42424243
       0x0000000000400986 <+6>:     je     0x40098f <_Z1fi+15>
       0x0000000000400988 <+8>:     lea    eax,[rdi-0x42424242]
       0x000000000040098e <+14>:    ret    
       0x000000000040098f <+15>:    push   rax
       0x0000000000400990 <+16>:    mov    edi,0x8
       0x0000000000400995 <+21>:    call   0x4007b0 <__cxa_allocate_exception@plt>
       0x000000000040099a <+26>:    xor    edx,edx
       0x000000000040099c <+28>:    mov    QWORD PTR [rax],0x400a54
       0x00000000004009a3 <+35>:    mov    esi,0x600f80
       0x00000000004009a8 <+40>:    mov    rdi,rax
       0x00000000004009ab <+43>:    call   0x4007d0 <__cxa_throw@plt>
    End of assembler dump.
    En suivant le déroulement de main, je ne vois nulle part ne fût-ce que la plus infime trace de code dédié à l'exception sur le chemin du code normal (réserver pile, lire entier, ajouter constante, appeler f, retourner).
    En suivant celui de f, je ne vois que le strict nécessaire : un unique saut conditionel, contrairement à un test de retour où il faudrait tester à chaque appel de fonction.

    Où est donc le coût des exceptions ? (A part dans le poids mémoire du runtime __cxa_*, qui sera probablement de toute façon inclus, sauf peut-être si -fno-exceptions est passé.)

Discussions similaires

  1. Réponses: 6
    Dernier message: 23/12/2014, 10h56
  2. Réponses: 0
    Dernier message: 01/11/2014, 17h48
  3. erreur en utilisant la bibliothèque de Facebook
    Par étudiante_info dans le forum Android
    Réponses: 3
    Dernier message: 19/04/2011, 16h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo