LinuxQuestions.org
View the Most Wanted LQ Wiki articles.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
LinkBack Search this Thread
Old 08-15-2012, 09:30 AM   #1
5883
Member
 
Registered: Aug 2004
Posts: 143

Rep: Reputation: 0
in which case the printf in c++ constructor will cause crash ?


if i just put printf in class constructor, it crashes,
any hints ?
 
Old 08-15-2012, 09:55 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 1,456

Rep: Reputation: 445Reputation: 445Reputation: 445Reputation: 445Reputation: 445
Use a debugger, it's quite likely your own fault. (You may quote some source code here, to help us help you.)
 
Old 08-15-2012, 11:39 AM   #3
sundialsvcs
Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 5,039

Rep: Reputation: 952Reputation: 952Reputation: 952Reputation: 952Reputation: 952Reputation: 952Reputation: 952Reputation: 952
A constructor is an initialization subroutine that is called when an object is being instantiated. The memory block has been allocated and partially initialized; the value has not yet been stored into whatever variable will contain the pointer to the finished object. In general, this is not a good place to "do" anything.

What I customarily do is to define another method, which I customarily call init(), which I call immediately after the contructor.

For instance, I will do: foo* foopy = new foo(); foopy->init();

Notice that the object has been fully instantiated, and stored into the variable ("foopy"), before in the next statement my init() routine is called.

Even if the init routine is "do-nothing" it is still my custom to call it. This is an "ordinary" method against an "ordinary" object by now, and it can therefore do anything it pleases.

In destructors, it is also my custom (painfully learned from an experience that literally cost me $10,000.00 ) to expressly set every local variable that points to something to NULL, in the very next statement. Also to bracket this with a try..finally block to make damn sure(!) that the pointer does not point to garbage, however briefly. Even if the free() call fails, the pointer still becomes NULL.

Last edited by sundialsvcs; 08-15-2012 at 11:40 AM.
 
Old 08-15-2012, 01:04 PM   #4
johnsfine
Senior Member
 
Registered: Dec 2007
Distribution: Centos
Posts: 4,963

Rep: Reputation: 1073Reputation: 1073Reputation: 1073Reputation: 1073Reputation: 1073Reputation: 1073Reputation: 1073Reputation: 1073
Quote:
Originally Posted by 5883 View Post
if i just put printf in class constructor, it crashes,
any hints ?
A wild guess, you tried to print the object being constructed and accidentally made another object of the same type causing a recursive call to the same constructor leading to a stack overflow crash.

If you would prefer better than a wild guess, provide code or more information.

It is not inherently wrong to call printf in a constructor, so you must have done something else wrong.
 
Old 08-15-2012, 02:54 PM   #5
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,494

Rep: Reputation: 327Reputation: 327Reputation: 327Reputation: 327
Quote:
Originally Posted by sundialsvcs View Post
The memory block has been allocated and partially initialized; the value has not yet been stored into whatever variable will contain the pointer to the finished object.
What are talking about? Perhaps you had a "bad day" whilst using the body of the constructor to initialize the class. The class should be initialized before entering the body of the constructor.

Code:
class Foo
{
public:
    Foo(const size_t reqDataSize);
    ~Foo();
private:
    char*  data;
    size_t dataSize;
};

...

Foo::Foo(const size_t reqDataSize)
    : data(new char[reqDataSize]),    // <--- this is the section where a class should be initialized
      dataSize(reqDataSize)
{
    // when we reach this point, the class is fully constructed, providing
    // of course, due diligence is applied when filling in the area above.

    // now, at this point we may want to perform "sanity" check on class members
    // or perhaps even initialize the data with values.
    if (!data)
    {
        throw WeAreOutOfMemory();
    }
    for (size_t i = 0; i < dataSize; ++i)
    {
        data[i] = 'a' + (rand() % 26);
    }
}

Foo::~Foo()
{
    delete [] data;
}
Quote:
Originally Posted by sundialsvcs View Post
What I customarily do is to define another method, which I customarily call init(), which I call immediately after the contructor.
In certain cases, this approach is useful, but not for the reason you pointed out earlier.

Quote:
Originally Posted by sundialsvcs View Post
In destructors, it is also my custom (painfully learned from an experience that literally cost me $10,000.00 ) to expressly set every local variable that points to something to NULL, in the very next statement. Also to bracket this with a try..finally block to make damn sure(!) that the pointer does not point to garbage, however briefly. Even if the free() call fails, the pointer still becomes NULL.
I'm not sure why you care whether a pointer is pointing to NULL after it has been freed. As long as you don't use it after it has been freed, your application should be fine. As for the object that contains the dangling pointer, even it should not be used after the destructor has been invoked.

In the example I demonstrated earlier, a smart-pointer (e.g. boost::shared_array) would be preferable to use than a raw pointer. That way I would not have to worry about freeing the allocated memory when the class object is destroyed.

Everyone has unique experiences in life, and I would be entertained to hear how you lost $10K on a project.
 
Old 08-15-2012, 04:50 PM   #6
5883
Member
 
Registered: Aug 2004
Posts: 143

Original Poster
Rep: Reputation: 0
Thanks for everyone's help, my case is pretty different, this is running in a ARM board,
i suspect missing correct libs, also some memory corruption before i new the object ...

For following might not be from the constructor, but gives you some info,

Program terminated with signal 11, Segmentation fault.
#0 0x40836fbc in malloc_get_state () from /lib/libc.so.6
(gdb) bt
#0 0x40836fbc in malloc_get_state () from /lib/libc.so.6
#1 0x408059cc in vfprintf () from /lib/libc.so.6
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
 
Old 08-15-2012, 06:42 PM   #7
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,494

Rep: Reputation: 327Reputation: 327Reputation: 327Reputation: 327
Quote:
Originally Posted by 5883 View Post
Thanks for everyone's help, my case is pretty different, this is running in a ARM board,
i suspect missing correct libs, also some memory corruption before i new the object ...

For following might not be from the constructor, but gives you some info,

Program terminated with signal 11, Segmentation fault.
#0 0x40836fbc in malloc_get_state () from /lib/libc.so.6
(gdb) bt
#0 0x40836fbc in malloc_get_state () from /lib/libc.so.6
#1 0x408059cc in vfprintf () from /lib/libc.so.6
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Well thank God it's not from your code.
 
Old 08-15-2012, 07:36 PM   #8
johnsfine
Senior Member
 
Registered: Dec 2007
Distribution: Centos
Posts: 4,963

Rep: Reputation: 1073Reputation: 1073Reputation: 1073Reputation: 1073Reputation: 1073Reputation: 1073Reputation: 1073Reputation: 1073
Quote:
Originally Posted by 5883 View Post
i suspect missing correct libs
Strange guess. I really doubt that is correct.

Quote:
some memory corruption before i new the object
That is possible, but there are lots of possibilities since you provide no useful information.

Quote:
For following might not be from the constructor, but gives you some info,
That improbable stack fragment gives almost no information. Looking at that stack fragment, I would guess that some function overwrote its own return address on the stack so it did a wild jump when attempting to return, so it landed in malloc_get_state by accident. But I have no confidence in that guess.
 
1 members found this post helpful.
Old 08-16-2012, 06:31 AM   #9
bdd
LQ Newbie
 
Registered: Dec 2010
Posts: 1

Rep: Reputation: 0
Some possbilities come to mind:
- Is the object statically defined; i.e., not in a function? (though you did say you 'new' it)
- The printf format string does not match the items you have supplied (did you see a compiler warning?)
e.g.,
printf( "%s %s\n", "string1" );
- Did you specify a huge or negative field length?
- Is it possible that your compiler does not support the printf option(s) you are specifying? This is sometimes the case with embedded systems.

It would help to see the line of code (properly obfuscated, I suppose).
 
Old 08-16-2012, 09:31 AM   #10
sundialsvcs
Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 5,039

Rep: Reputation: 952Reputation: 952Reputation: 952Reputation: 952Reputation: 952Reputation: 952Reputation: 952Reputation: 952
Quote:
What are talking about? Perhaps you had a "bad day" whilst using the body of the constructor to initialize the class. The class should be initialized before entering the body of the constructor.

Code:
class Foo
{
public:
    Foo(const size_t reqDataSize);
    ~Foo();
private:
    char*  data;
    size_t dataSize;
};

...

Foo::Foo(const size_t reqDataSize)
    : data(new char[reqDataSize]),    // <--- this is the section where a class should be initialized
      dataSize(reqDataSize)
{
    // when we reach this point, the class is fully constructed, providing
    // of course, due diligence is applied when filling in the area above.

    // now, at this point we may want to perform "sanity" check on class members
    // or perhaps even initialize the data with values.
    if (!data)
    {
        throw WeAreOutOfMemory();
    }
    for (size_t i = 0; i < dataSize; ++i)
    {
        data[i] = 'a' + (rand() % 26);
    }
}

Foo::~Foo()
{
    delete [] data;
}
In certain cases, this approach is useful, but not for the reason you pointed out earlier.
At the time the constructor is executing, the object is indeed fully-formed, although perhaps not fully initialized, but the variable that will ultimately point to the object is still uninitialized with the correct value. Furthermore, there might be a chain of constructors of which this is only one. (You must be mindful of the situation where code worked just fine when originally written, but subsequent extensions or changes to the class structure cause it to later misbehave, etc.) Therefore, the overall situation is, shall we say, "a bit half-cooked."

Hence my practice of defining a separate "initialization" routine. This routine can safely assume not only that the object is fully prepared (no matter how many constructors may have fired), but that its surrounding context is truly ready-to-go. (I sometimes find it useful to do the same thing when an object is going-away, especially when the going-away process might involve, say, sending some kind of a notification message across a socket or an IPC connection or some-such.) In short, "this works for me." "This works really well for me." When you've just created someone, give 'em a moment to comb their hair. And, when you're about to shoot someone, give 'em that last cigarette.

Quote:
I'm not sure why you care whether a pointer is pointing to NULL after it has been freed. As long as you don't use it after it has been freed, your application should be fine. As for the object that contains the dangling pointer, even it should not be used after the destructor has been invoked.

In the example I demonstrated earlier, a smart-pointer (e.g. boost::shared_array) would be preferable to use than a raw pointer. That way I would not have to worry about freeing the allocated memory when the class object is destroyed.

Everyone has unique experiences in life, and I would be entertained to hear how you lost $10K on a project.
The $10,000 problem was ultimately a "double free," in code that I bought but did not write, in a language other than C++. The destructor freed the memory then called the parent. The parent destructor in the destructor chain attempted to reference the non-NULL pointer that now pointed to freed data. In the case at bar (Windows 3.1) not only the application but the entire operating environment disappeared: one moment you're running a mission-critical app; the next instant you're at a MS-DOS prompt, and everything you need to resolve the problem is gone. (Even exception-handling did not work.) I could not resolve the issue and had to give a fat refund. (The story has a somewhat happy ending because the customer was so impressed that we were willing to do what our contract promised, that he didn't sell us down the river.)

Last edited by sundialsvcs; 08-16-2012 at 09:38 AM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Constructor takes string => constructor not called...? (C++) JohnGraham Programming 4 02-16-2012 12:37 PM
LXer: Linux: The Case Against Crash Dumps LXer Syndicated Linux News 0 05-26-2007 05:01 AM
How could a program crash between 2 printf() 's? paul76 Programming 12 09-11-2003 12:17 PM


All times are GMT -5. The time now is 11:14 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration