Jump to content
Sign in to follow this  
feron_jb

Segmentation fault after pointer content copy

Recommended Posts

Hello,

 

I have a strange beahavior of a systemC program caused by a debug function.

This function (called memItemExamine) allows to read a memory cell in a sub-module (memDev in the example) from the top level class (Model_top in the example).

The particularity of that error lies in the fact that I can read the memory cell (content is correctly displayed in terminal), but when later a process comes to read the memory cell again, the program fails with a segmentation fault.

Please find a simplified example of my codes hereunder, they illustrate the hierarchy of my program and the methodology I use to implement the memItemExamine function.

 

Any comment or feedback is welcome.

Do not hesitate to give me SystemC debug advices, I almost found nothing on internet about it (another topic could arrive on that subject regarding Eclipse CDT debug environment).

memDev.h :

One of the systemC thread implements an array of pointers which represent the memory cells. Initialisation of the pointers is not shown in the code but it is done.

SC_MODULE (memDev){
public :
    memItem** itemArray;
    void readmemItem(int address, memItem** ppReadItem);
    SC_HAS_PROCESS(memDev);
    memDev(sc_module_name instname) : sc_module(instname) {
        SC_THREAD(execute);
            itemArray  = new memItem*[100];
            // Memory initialization performed
    }
};

memDev.cpp

void memDev::execute(){
    while(true){
        ...
        wait(20, SC_NS);
    };

void memDev::readmemItem(int address, memItem** ppReadItem){
    *ppReadItem = itemArray[address]->content;    
};

Model_top.h :

memItemExamine function copy the memory cell content in the provided pointer readItem.

#include "memDev.h"
#include "otherDev.h"    // Not important here
class Model_top {
    memDev my_memDev;    // SystemC thread
    otherDev my_otherDev;    //SystemC thread
    Model_top();
    void memItemExamine(int address, memItem* readItem);
}

Model_top.cpp

Model_top::Model_top():
        my_memDev("my_memDev"),
        my_otherDev("my_otherDev"){
}

void Model_top::memItemExamine(int address, memItem* readItem){
    memItem** tempVal = new memItem*;
    my_memDev.readmemItem(address, tempVal);
    readItem->content = (*tempVal)->content;
    delete tempVal;
}

main.cpp :

If the memItemExamine function is not executed, no segmentation fault occurs.

int sc_main(int argc, char* argv[]) {

    Model_top my_modelTop;

    // sc_start(30, SC_NS);   // Possibility to start simulation before examine

// Memory item examine (debug purpose)
    memItem* pmemItem = new memItem;
    modelTop.memItemExamine(1, pmemItem);
    cout << pmemItem->content << endl;    // Content is displayed

// Segmentation fault occurs here :
    sc_start(70, SC_NS);

    return 0;
};

Thank you for your time!

Regards,

J-B

 

Share this post


Link to post
Share on other sites

Assuming you're on Unix/Linux, I would run the program under gdb, then when it crashes do a stack backtrace (the bt command). That will show you exactly where the error occurs.

 

Once you know where the error occurs, put in print statements to find out the values of the various pointers and so on,

 

regards

Alan

Share this post


Link to post
Share on other sites

Hello,

 

I have a strange beahavior of a systemC program caused by a debug function.

This function (called memItemExamine) allows to read a memory cell in a sub-module (memDev in the example) from the top level class (Model_top in the example).

The particularity of that error lies in the fact that I can read the memory cell (content is correctly displayed in terminal), but when later a process comes to read the memory cell again, the program fails with a segmentation fault.

Please find a simplified example of my codes hereunder, they illustrate the hierarchy of my program and the methodology I use to implement the memItemExamine function.

 

Any comment or feedback is welcome.

Do not hesitate to give me SystemC debug advices, I almost found nothing on internet about it (another topic could arrive on that subject regarding Eclipse CDT debug environment).

memDev.h :

One of the systemC thread implements an array of pointers which represent the memory cells. Initialisation of the pointers is not shown in the code but it is done.

SC_MODULE (memDev){
public :
    memItem** itemArray;
    void readmemItem(int address, memItem** ppReadItem);
    SC_HAS_PROCESS(memDev);
    memDev(sc_module_name instname) : sc_module(instname) {
        SC_THREAD(execute);
            itemArray  = new memItem*[100];
            // Memory initialization performed
    }
};

memDev.cpp

void memDev::execute(){
    while(true){
        ...
        wait(20, SC_NS);
    };

void memDev::readmemItem(int address, memItem** ppReadItem){
    *ppReadItem = itemArray[address]->content;    
};

Model_top.h :

memItemExamine function copy the memory cell content in the provided pointer readItem.

#include "memDev.h"
#include "otherDev.h"    // Not important here
class Model_top {
    memDev my_memDev;    // SystemC thread
    otherDev my_otherDev;    //SystemC thread
    Model_top();
    void memItemExamine(int address, memItem* readItem);
}

Model_top.cpp

Model_top::Model_top():
        my_memDev("my_memDev"),
        my_otherDev("my_otherDev"){
}

void Model_top::memItemExamine(int address, memItem* readItem){
    memItem** tempVal = new memItem*;
    my_memDev.readmemItem(address, tempVal);
    readItem->content = (*tempVal)->content;
    delete tempVal;
}

main.cpp :

If the memItemExamine function is not executed, no segmentation fault occurs.

int sc_main(int argc, char* argv[]) {

    Model_top my_modelTop;

    // sc_start(30, SC_NS);   // Possibility to start simulation before examine

// Memory item examine (debug purpose)
    memItem* pmemItem = new memItem;
    modelTop.memItemExamine(1, pmemItem);
    cout << pmemItem->content << endl;    // Content is displayed

// Segmentation fault occurs here :
    sc_start(70, SC_NS);

    return 0;
};

Thank you for your time!

Regards,

J-B

 

Hello Sir.

First of all, please stay away from Eclipse and

similar IDEs when programming in essentially

a command line driven environmsnt, to reduce

complexity, and remove the bothersome task

of having to tackle strange errors arising from

some configuration/environment variable not

being set correctly.

 

First of all, the statement :

itemArray  = new memItem*[100];

initializes itemArray to an array of pointers to

100 memItems, NOT 100 memItems. Where

is the array of memItems?

 

Now note that segmentation faults mostly arise

from trying to de-reference a NULL pointer.

The signature of readmemItem in module memDev is:

void memDev::readmemItem(int address, memItem** ppReadItem){

    *ppReadItem = itemArray[address]->content;    

};

 

So a pointer-to-pointer ppReadItem is passed to the method. and

execution of : *ppReadItem = itemArray[address]->content;

provides a pointer to itemArray[address]->content;

 

Now in Model_top module :

void Model_top::memItemExamine(int address, memItem* readItem){

    memItem** tempVal = new memItem*;

    my_memDev.readmemItem(address, tempVal);

    readItem->content = (*tempVal)->content;

    delete tempVal;

}

 

The code is unfortunately very complicated: The final aim is to copy

the contents at a certain address in the array.of memItems. So the

questions are:

1. Where is the array of menOtems NOT the pointers to memItems.

2. The unnecessary step of creating a pointer-to-pointer and ten

transferring the contents to readItem can be removed, and the

code made more transparent.

Most importantly, the segmentation fault arises because the memItems

DO NOT EXIST, only an array of pointers to memItems. Please address

this issue.

I personally love manipulating pointers, but one has to be careful

to ensure that the pointers point to some real object.

Hope that helps.

Share this post


Link to post
Share on other sites

Hi,

Thank you for your answers.

 

@dakupoto :

I noticed your advices about Eclipse. I am using it for its dynamic error detection which is really useful and makes me gain a lot of time. If you have lighter solution, please share.

Regarding my example, I am indeed using a lot of pointers which make it difficult to understand and debug. However, as I said in my initial post, I initialize my table of pointers itemArray correctly as I can read the content, I just do not show the initialization code in the example. The error is not in my pointer use, I think, but instead in my use of some systemC function (see GDB results hereunder).

I need more an external point of view on my methodology of examining the array content because I think the error is there.

I however note that some improvement in the pointer content copy could be made.

 

@apfitch :

Indeed, GDB seems really easy.

Here is the GDB output :

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b22313 in sc_core::vcd_trace_file::initialize() ()
   from /usr/local/systemc-2.3.0/lib-linux64/libsystemc-2.3.0.so

(gdb) backtrace
#0  0x00007ffff7b22313 in sc_core::vcd_trace_file::initialize() ()
   from /usr/local/systemc-2.3.0/lib-linux64/libsystemc-2.3.0.so
#1  0x00007ffff7b22950 in sc_core::vcd_trace_file::cycle(bool) ()
   from /usr/local/systemc-2.3.0/lib-linux64/libsystemc-2.3.0.so
#2  0x00007ffff7afc543 in sc_core::sc_simcontext::trace_cycle(bool) ()
   from /usr/local/systemc-2.3.0/lib-linux64/libsystemc-2.3.0.so
#3  0x00007ffff7aff92a in sc_core::sc_simcontext::simulate(sc_core::sc_time const&) () from /usr/local/systemc-2.3.0/lib-linux64/libsystemc-2.3.0.so
#4  0x00007ffff7afffb1 in sc_core::sc_start(sc_core::sc_time const&, sc_core::sc_starvation_policy) ()
   from /usr/local/systemc-2.3.0/lib-linux64/libsystemc-2.3.0.so
#5  0x000000000042bb9e in sc_core::sc_start (duration=70, unit=sc_core::SC_NS,
    p=sc_core::SC_RUN_TO_TIME)
    at /usr/local/systemc-2.3.0/include/sysc/kernel/sc_simcontext.h:112
#6  0x000000000042b204 in sc_main (argc=1, argv=0x6748f0)
    at Testbenches/TB_CLP_top.cpp:151
#7  0x00007ffff7aed7e3 in sc_elab_and_sim ()
   from /usr/local/systemc-2.3.0/lib-linux64/libsystemc-2.3.0.so
#8  0x00007ffff71c876d in __libc_start_main ()
   from /lib/x86_64-linux-gnu/libc.so.6
#9  0x0000000000405019 in _start ()

It seem to come from the SystemC library.

Any idea about what happens?

 

Thank you & have a nice WE!

J-B

Share this post


Link to post
Share on other sites

Hi,

Thank you for your answers.

 

@dakupoto :

I noticed your advices about Eclipse. I am using it for its dynamic error detection which is really useful and makes me gain a lot of time. If you have lighter solution, please share.

Regarding my example, I am indeed using a lot of pointers which make it difficult to understand and debug. However, as I said in my initial post, I initialize my table of pointers itemArray correctly as I can read the content, I just do not show the initialization code in the example. The error is not in my pointer use, I think, but instead in my use of some systemC function (see GDB results hereunder).

I need more an external point of view on my methodology of examining the array content because I think the error is there.

I however note that some improvement in the pointer content copy could be made.

 

@apfitch :

Indeed, GDB seems really easy.

Here is the GDB output :

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b22313 in sc_core::vcd_trace_file::initialize() ()
   from /usr/local/systemc-2.3.0/lib-linux64/libsystemc-2.3.0.so

(gdb) backtrace
#0  0x00007ffff7b22313 in sc_core::vcd_trace_file::initialize() ()
   from /usr/local/systemc-2.3.0/lib-linux64/libsystemc-2.3.0.so
#1  0x00007ffff7b22950 in sc_core::vcd_trace_file::cycle(bool) ()
   from /usr/local/systemc-2.3.0/lib-linux64/libsystemc-2.3.0.so
#2  0x00007ffff7afc543 in sc_core::sc_simcontext::trace_cycle(bool) ()
   from /usr/local/systemc-2.3.0/lib-linux64/libsystemc-2.3.0.so
#3  0x00007ffff7aff92a in sc_core::sc_simcontext::simulate(sc_core::sc_time const&) () from /usr/local/systemc-2.3.0/lib-linux64/libsystemc-2.3.0.so
#4  0x00007ffff7afffb1 in sc_core::sc_start(sc_core::sc_time const&, sc_core::sc_starvation_policy) ()
   from /usr/local/systemc-2.3.0/lib-linux64/libsystemc-2.3.0.so
#5  0x000000000042bb9e in sc_core::sc_start (duration=70, unit=sc_core::SC_NS,
    p=sc_core::SC_RUN_TO_TIME)
    at /usr/local/systemc-2.3.0/include/sysc/kernel/sc_simcontext.h:112
#6  0x000000000042b204 in sc_main (argc=1, argv=0x6748f0)
    at Testbenches/TB_CLP_top.cpp:151
#7  0x00007ffff7aed7e3 in sc_elab_and_sim ()
   from /usr/local/systemc-2.3.0/lib-linux64/libsystemc-2.3.0.so
#8  0x00007ffff71c876d in __libc_start_main ()
   from /lib/x86_64-linux-gnu/libc.so.6
#9  0x0000000000405019 in _start ()

It seem to come from the SystemC library.

Any idea about what happens?

 

Thank you & have a nice WE!

J-B

 

Hello Sir,

While the GDB error trace shows that the SystemC 2.3.0

library is hiccuping on trace file creation/manipulation, the

source code samples supplied do not show any code that

generates the VCD traces. I have used VCD traces over

and over with SystemC 2.3.0 and the previous SystemC

2.2.0. and never had any problems. The following code

snippet a typical way of using VCD trace generation scheme,

invoked from inside main.cpp.

 

  sc_core::sc_trace_file *fp;

  fp = sc_core::sc_create_vcd_trace_file("<trace_file_name>");

  fp->set_time_unit(1.0, sc_core::<time_unit>);

  sc_trace(fp, <signal_A>, "<signal_A_name>");

  sc_trace(fp, <signal_B>, "<signal_B_name>");

  /* Add more signals as needed */

  sc_core::sc_start(<total time period for simulation>, sc_core::<time_unit>);

  sc_core::sc_stop();

  sc_core::sc_close_vcd_trace_file(fp);

  return 0;

 

The VCD files can be viewed easily with GTKWave.

 

Segmentation faults, are caused almost always

when a NULL pointer is being de-referenced. So

one way to detect the point of failure would be to

"step through " the code with GDB, and check

variable values after execution of each step,

specially where each pointer is pointing to.

 

In the past, I have found that configuring Eclipse

to point to the correct compiler is a complicated

and error-prone, and so I do all my work with

simple Makefiles. Makefiles are very efficient

and extremely editable.

 

HTH.

Share this post


Link to post
Share on other sites

I observe that the only place in the code where the construct new memItem occurs is in your debug routine. It's no wonder that you crash without it, since the initial array uninitialized ponters. Nowhere do we see the definition of memItem, and nowhere do we see the array properly initialized. Also, I do not see any array bounds checking in the provided code. I would expect numerous problems with this coding approach.

 

Good programmers learn to minimize pointers by relegating them to low-level constructs and using RAII techniques. Good C++ programmers will utilize STL concepts such as std::vector (or std::array) and std::unique_ptr

 

Consider using:

struct memItem {
  int content;

  memItem() // Constuctor
  :content(0) // Proper initialization
  {}

};

std::array<memItem,100> itemArray;

# You can now access items in the array with:
#   memArray.at(i) = newValue; //< set a value
#   existingValue = memArray.at(i); // get a value
# 

Share this post


Link to post
Share on other sites

I finally found a bug caused by an uninitialized pointer.

I had to extensively use the command line GDB and discovered a really powerful debug tool, more reliable than the graphical GDB integrated to Eclipse CDT.

 

Thank you also for your useful advices about GDB use, pointer initialization, etc.

Share this post


Link to post
Share on other sites

I finally found a bug caused by an uninitialized pointer.

I had to extensively use the command line GDB and discovered a really powerful debug tool, more reliable than the graphical GDB integrated to Eclipse CDT.

 

Thank you also for your useful advices about GDB use, pointer initialization, etc.

That is extremely good to hear. I am sure you have realized what a

double edged sword pointers are.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×