c++ - (not) using std::string in exceptions -


i'm reading should not throw std::string or other classes allocating memory. here or more importantly here on point 3. - don't embed std::string object.

so i'm trying insert boost::exception project , see: lots of strings.

why doesn't boost comply own recommendation?

and if have parameters can't hardcoded, safed in config-file, how can put them exception, without using std::string?

or guideline don't use std::string do use std::string seldom possible guideline? i'm bit confused...

i've done research. please correct me if i'm wrong.


if understand right, it's allocation during throw , happening allocated memory. memory gets lost if allocate in constructor , can't freed in destructor of exception, produce memory-leak. it's okay allocate before throwing, exception clean.

i tried this:

struct xexception {   int *ttt[10];   xexception() {     ttt[0] = new int[0xfffffffl];     ttt[1] = new int[0xfffffffl];     ttt[2] = new int[0xfffffffl];     ttt[3] = new int[0xfffffffl];     ttt[4] = new int[0xfffffffl];     ttt[5] = new int[0xfffffffl];     ttt[6] = new int[0xfffffffl];     ttt[7] = new int[0xfffffffl];     ttt[8] = new int[0xfffffffl];     ttt[9] = new int[0xfffffffl];   }    ~xexception() throw() {     //never happen     delete[] ttt[0];     delete[] ttt[1];     delete[] ttt[2];     delete[] ttt[3];     delete[] ttt[4];     delete[] ttt[5];     delete[] ttt[6];     delete[] ttt[7];     delete[] ttt[8];     delete[] ttt[9];   } };  int main(int argc, const char *argv[]) {   try {     throw(xexception());   }   catch (const xexception &e) {     std::cerr << "\nttt " << e.ttt[0][0] << std::endl;   }   catch (std::bad_alloc) {     std::cerr << "bad alloc" << std::endl;   }    return 0; } 

the result is, bad_alloc , huge memory leak.

now if allocation before, also throws bad_alloc before exception created.


my exception exception concept is:

who cares? if have bad_alloc in program, because of memory_leak or else (i'm talking programs on pcs not microcontrollers) have other problems. maybe can figure out bad_alloc happened, where? on alloc during function (one of maybe 1000) or in std::string (well know it's string ... no possibility manipulate memory of string... or dissipated).

try {   // error???   int *x = new int[100];  // here?   ....   int *y = new int[100];  // or here?   ....   int *z = new int[100];   ....   int *w = new int[100];   ....   int *t = new int[100];   ....   int *f = new int[100];    ....    std::string str("asdfasdfasdfasdfasdfasdfasdf"); // maybe here } catch (the error) {   .... } 

and then? shall try figure out it's happening? therefore use valgrind not exceptions.

void foo() {   int *i = new int[1];   foo(); }  try {   foo(); } chatch( bad_boy ) {   go_exception_handler_go(parameters); // oh, shit happens: stack_overflow may happend, cause stack full } 

or shall manipulate errormessage , log it, definitively throw next bad_alloc.

please don't misunderstand me. since i've seen boost::exception i've rewritten exception class (till waiting on answer) think not necessary pick every grain of sand.

the advice telling "don't use construct might throw exception in exception". that's because if exception while trying throw exception, c++ runtime call terminate() , kill program.

now if (either) of exceptions involved call terminate() anyways (as default uncaught exception), don't need worry it. example, if application can't handle bad_alloc (can't recover out-of-memory), don't need worry copy constructors (such std::string) might throw it.

but if want able catch , recover bad_alloc, need ensure none of exception copy constructors can cause one. if you're writing library other applications use, should not assume application not want handle bad_alloc.

c++11 make easier using move constructors (instead of copy constructors) possible. since move constructor std::string never throws exceptions can safely use std:string in exception type long implement move constructors, , ensure used. note initial construction of object thrown in throw expression not part of exception throwing process, constructor can throw exception without causing double exception (and terminate()). if have:

throw some_function(); 

some_function might throw exception (such bad_alloc) without returning object thrown , that's fine. if doesn't throw exception (and returns valid object), move constructor exception type used (if available) exception throwing process, , move constructor must not throw exception.


completely independent of above, whenever call new need ensure 1 spot call delete in every possible case, or you'll leak memory (or crash double delete). becomes tricky time have function calls new , else might throw exception (such call new again). if happens in constructor, destructor object not called (though destructors base classes , fields be), can't cleanup in destructor trying example.

fortunately std::unique_ptr exists make easier. if write exception class as:

struct xexception {   std::unique_ptr<int[]> ttt[10];   xexception() {     ttt[0].reset(new int[0xfffffffl]);     ttt[1].reset(new int[0xfffffffl]);     ttt[2].reset(new int[0xfffffffl]);     ttt[3].reset(new int[0xfffffffl]);     ttt[4].reset(new int[0xfffffffl]);     ttt[5].reset(new int[0xfffffffl]);     ttt[6].reset(new int[0xfffffffl]);     ttt[7].reset(new int[0xfffffffl]);     ttt[8].reset(new int[0xfffffffl]);     ttt[9].reset(new int[0xfffffffl]);   } }; 

it should work , not leak memory.


Comments

Popular posts from this blog

monitor web browser programmatically in Android? -

Shrink a YouTube video to responsive width -

wpf - PdfWriter.GetInstance throws System.NullReferenceException -