Prev: Namespace vs. isnan
Next: strcpy_s vs strcpy
From: Daniel Krügler on 16 Apr 2008 18:56 On 16 Apr., 23:43, mpho <tjab...(a)gmail.com> wrote: > This seems straightforward but gives this runtime error: terminate > called after throwing an instance of 'std::bad_alloc' , what() : > std9bad_alloc . I have: > > class X { > int sz; > T *ptr; > > public: > X(int s, T *p) : sz(s), ptr(new T[s]) Note that you are invoking the array form of new here, new[]. > { > assert(ptr != NULL); > for (int i = 0, i < sz; i++) > ptr[i] = p[i]; > } > > //other members > > ~X() { delete ptr; ptr = NULL; } .... And here you are using the scalar form of delete - undefined behaviour, see [expr.delete]/2. To fix this, use delete[] ptr; instead (The final nullification of ptr in the d'tor is essentially superfluous). > }; > > class Y { > X xobj > > public: > Y(int s, T *p) : xobj(s, p) { } //OK? > //other members > ~Y() { } //OK? > }; > > then > > int main(){ > > ar[10] = {ten values}; > Y yobj(10, ar); //problem here(?) > ...... > ..... > > } > > What's the problem above? > Thank you. There are several syntactic issues and missing code, but the new[]/delete mismatch is probably your main problem. Basic rule 1: Always combine new/delete and new[]/delete[]. Basic rule 2: If possible, replace "manual" resource allocations and use a full-fledged class for doing this - this is the basic idiom of RAII (Resource Acquisition Is Initialization). Your example code above is the classical use-case for std::vector<T> and there is little excuse for not using it here. HTH & Greetings from Bremen, Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Gerhard Menzl on 16 Apr 2008 18:59 mpho wrote: > This seems straightforward but gives this runtime error: terminate > called after throwing an instance of 'std::bad_alloc' , what() : > std9bad_alloc . I have: > > class X { > int sz; > T *ptr; Unknown type T. > > public: > X(int s, T *p) : sz(s), ptr(new T[s]) > { > assert(ptr != NULL); What's the purpose of the assert here? Do you want to make sure the standard allocator is working correctly? Unless you have overloaded new[] and implemented it incorrectly, ptr cannot ever be null here. > for (int i = 0, i < sz; i++) Syntax error. > ptr[i] = p[i]; > } > > //other members > > ~X() { delete ptr; ptr = NULL; } Undefined behaviour. What has been allocated via new[] requires delete[]. Besides, setting ptr to null is as gratuitous as the assert before. ptr cannot be legally accessed anymore after the destructor has executed. > }; > > class Y { > X xobj Missing semicolon. > > public: > Y(int s, T *p) : xobj(s, p) { } //OK? > //other members > ~Y() { } //OK? > }; > > then > > int main(){ > > ar[10] = {ten values}; Unknown identifer ar. If this is supposed to be its definition, where is the type? > Y yobj(10, ar); //problem here(?) > ...... > ..... Syntax error. > } > What's the problem above? > Thank you. The main problem is that you submit ill-formed and incomplete code and expect others to correct the obvious errors and guess the not so obvious bits that are missing. Without knowing what T is, it is impossible to say what is going on. The only glaring runtime problem is the new[]/delete mismatch, but I doubt that it would cause std::bad_alloc to be thrown (although with undefined behaviour, anything is possible). The most likely cause is inifinite recursion somewhere in the code you have not shown, which causes the free store to be exhausted. -- Gerhard Menzl Non-spammers may respond to my email address, which is composed of my full name, separated by a dot, followed by at, followed by "fwz", followed by a dot, followed by "aero". [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Mathias Gaunard on 16 Apr 2008 18:56 On 16 avr, 23:43, mpho <tjab...(a)gmail.com> wrote: > class X { > int sz; > T *ptr; > > public: > X(int s, T *p) : sz(s), ptr(new T[s]) > { > assert(ptr != NULL); > for (int i = 0, i < sz; i++) > ptr[i] = p[i]; ptr[i] = p[i] can throw. If it does, you need to call delete[] on ptr. > ~X() { delete ptr; ptr = NULL; } You should use delete[], not delete. Calling delete on something allocated with new[] is undefined behaviour. ptr = NULL is also totally useless in a destructor. By the way, the automatically defined operator= and copy constructor will mess everything up. Either disable them, or write them to do deep- copying. > class Y { > X xobj > > public: > Y(int s, T *p) : xobj(s, p) { } //OK? > //other members > ~Y() { } //OK? > }; That's OK, yes. > ar[10] = {ten values}; That doesn't seem to be valid C++ syntax. > Y yobj(10, ar); //problem here(?) None at that line. > What's the problem above? How is a std::bad_alloc being raised a problem? It could just means you're out of memory. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Chris Uzdavinis on 16 Apr 2008 19:13 On Apr 16, 5:43 pm, mpho <tjab...(a)gmail.com> wrote: > X(int s, T *p) : sz(s), ptr(new T[s]) > { > assert(ptr != NULL); > for (int i = 0, i < sz; i++) > ptr[i] = p[i]; > } Your assertion can never fail, since "new" throws a std::bad_alloc when it fails. Therefore, the assertion is misleading and should probably be removed. > //other members > ~X() { delete ptr; ptr = NULL; } > }; Whoops! Your destructor must perform the array form of deletion: delete [] ptr; There is no need to set ptr to NULL afterwords, since as soon as we exit the destructor, the object containing ptr no longer exists, and its members can never be accessed again. > int main(){ > > ar[10] = {ten values}; > Y yobj(10, ar); //problem here(?) > ...... > ..... > > } > > What's the problem above? 1) ar has no type 2) "ten values" is pseudocode 3) Any uncaught exception (that can unwind the stack past main) will cause std::terminate() to be called. Since there are no try/catch blocks in your program, and you say an exception is occurring, it should be of little surprise that your program terminates. -- Chris [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: mpho on 17 Apr 2008 21:13
On Apr 17, 7:13 pm, Chris Uzdavinis <cuz...(a)gmail.com> wrote: > On Apr 16, 5:43 pm, mpho <tjab...(a)gmail.com> wrote: > > > X(int s, T *p) : sz(s), ptr(new T[s]) > > { > > assert(ptr != NULL); > > for (int i = 0, i < sz; i++) > > ptr[i] = p[i]; > > } > > Your assertion can never fail, since "new" throws a std::bad_alloc > when it fails. Therefore, the assertion is misleading and should > probably be removed. > > > //other members > > ~X() { delete ptr; ptr = NULL; } > > }; > > Whoops! Your destructor must perform the array form of deletion: > > delete [] ptr; > > There is no need to set ptr to NULL afterwords, since as soon as we > exit the destructor, the object containing ptr no longer exists, and > its members can never be accessed again. > > > int main(){ > > > ar[10] = {ten values}; > > Y yobj(10, ar); //problem here(?) > > ...... > > ..... > > > } > > > What's the problem above? > > 1) ar has no type > > 2) "ten values" is pseudocode > > 3) Any uncaught exception (that can unwind the stack past main) will > cause std::terminate() to be called. Since there are no try/catch > blocks in your program, and you say an exception is occurring, it > should be of little surprise that your program terminates. { edits: quoted signature and banner (see the end of this article) removed, please don't quote extraneous material -- even if the clc++m banner is a very fine one. -mod } Dear all, The obvious errors have really been mistypes and not deliberate. I apologize. Thanks for the replies, the problem still persists. The complete code, excluding the unnecessary stuff by your comments, is: typedef T //something class X { int sz; T *ptr; public: X(int s, T *p) : sz(s), ptr(new T[s]) { for (int i = 0, i < sz; i++) ptr[i] = p[i]; } X(const X& other); X& operator=(const X&); ~X() { delete [] ptr; } }; class Y { X xobj; public: Y(int s, T *p) : xobj(s, p) { } //other members ~Y() { } }; No problem with copy constructor and assignment. int main(){ T ar[10] = {1,2,3,4,5,6,7,8,9,10}; Y yobj(10, ar); //problem here(?) ....... ...... } No try/catch blocks in the program. Should this not work? -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |