feron_jb Posted February 27, 2014 Report Posted February 27, 2014 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 ygurcxinkq 1 Quote
apfitch Posted February 27, 2014 Report Posted February 27, 2014 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 David Black 1 Quote
dakupoto Posted February 28, 2014 Report Posted February 28, 2014 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. Quote
feron_jb Posted February 28, 2014 Author Report Posted February 28, 2014 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 Quote
apfitch Posted March 1, 2014 Report Posted March 1, 2014 The backtrace seems to be pointing at Testbenches/TB_CLP_top.cpp:151, so I'd start looking there, Alan Quote
dakupoto Posted March 1, 2014 Report Posted March 1, 2014 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. Quote
David Black Posted March 5, 2014 Report Posted March 5, 2014 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 # Quote
feron_jb Posted March 5, 2014 Author Report Posted March 5, 2014 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. Quote
dakupoto Posted March 6, 2014 Report Posted March 6, 2014 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. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.