lldb unresolved breakpoint via c++ api - c++

I have got executable module iCoreTest.exe, wich dynamicly loaded library IRTest.rs. I want to debug it via lldb c++ api.
When I create "iCoreTest.exe" process under lldb throug lldb::SBTarget::Launch(..); everything works fine. With fine, I mean I can set breakpoints BreakpointCreateByLocation and when the debugger stops on it get the event from SBListener.WaitForEvent();
Problems begins when I want to attach to the currently running process.
Create target and attach to process
m_debugData->currentTarget=m_debugData>debugger.CreateTarget(executable.c_str());
m_debugData->currentProcess = m_debugData>currentTarget.AttachToProcessWithName(m_debugData->listener, processName.c_str(), false, error);
Load module "IRTest.rs"
auto module = m_debugData->currentTarget.AddModule("IRTest.rs", "i386-pc-windows-msvc", nullptr);
After that lldb stops on "ntdll.dll`DbgBreakPoint + 1"
I execute command m_debugData->currentProcess.Continue();
So, ICoreTest.exe is running..
Add breakpoint m_debugData->currentTarget.BreakpointCreateByLocation("IRTest.st", 58);
The added breakpoint does not triggered
After this I print the existing breakpoints using the following code:
void LLDBRunner::printBreakpoints()
{
for (int i = 0; i < m_debugData->currentTarget.GetNumBreakpoints(); i++)
{
auto bp = m_debugData->currentTarget.GetBreakpointAtIndex(i);
for (int j = 0; j < bp.GetNumLocations(); j++)
{
auto loc = bp.GetLocationAtIndex(j);
lldb::SBStream stream;
loc.GetDescription(stream, lldb::DescriptionLevel::eDescriptionLevelFull);
auto str = stream.GetData();
}
}
}
And output was:
1.1: where = IRTest.rs`Add + 421 at IRTest.st:58, address = IRTest.rs[0x10001525], unresolved, hit count = 0
Which means my breakpoint is unresolved..Why? :)
Also!
When i use lldb command line breakpoint is resolved, and working:
(lldb) attach -p 17448
Process 17448 stopped
* thread #1: tid = 0x0ae0, 0x77bc8d21 ntdll.dll`DbgBreakPoint + 1, stop reason = Exception 0x80000003 encountered at address 0x77bc8d20
frame #0: 0x77bc8d21 ntdll.dll`DbgBreakPoint + 1
ntdll.dll`DbgBreakPoint:
-> 0x77bc8d21 <+1>: retl
0x77bc8d22 <+2>: int3
0x77bc8d23 <+3>: int3
0x77bc8d24 <+4>: int3
Executable module set to "iCoreTest.exe".
Architecture set to: i386-pc-windows-msvc.
(lldb) b IRTest.st:58
Breakpoint 1: where = IRTest.rs`Add + 421 at IRTest.st:58, address = 0x07ca1525
(lldb) b
Current breakpoints:
1: file = 'IRTest.st', line = 58, exact_match = 0, locations = 1, resolved = 1, hit count = 0
1.1: where = IRTest.rs`Add + 421 at IRTest.st:58, address = 0x07ca1525, resolved, hit count = 0
(lldb) c
Process 17448 resuming
Process 17448 stopped
* thread #6: tid = 0x2560, 0x07ca1525 IRTest.rs`Add(X1=2, X2=42, X3=(RANGE = 1, MIN_SCALE = -4095, MAX_SCALE = 4095)) + 421 at IRTest.st:58, stop reason = breakpoint 1.1
frame #0: 0x07ca1525 IRTest.rs`Add(X1=2, X2=42, X3=(RANGE = 1, MIN_SCALE = -4095, MAX_SCALE = 4095)) + 421 at IRTest.st:58
55 i, j : INT;
56 END_VAR
57
-> 58 tmpInteg();
59
60
61
(lldb)
UPDATE:
I write a simple program wich reproduce bug
prog.cpp:
#include <cstdio>
void doSomething(void);
void doSomething(void)
{
int loop = 0;
loop += 1;
loop += 2;
loop += 3;
}
int main(void)`
{
printf("start \n");
while(1)
{
doSomething();
}
return 0;
}
Compile it..
gcc prog.cpp -g -O0
When i`m trying to set break point
m_debugData->currentTarget.BreakpointCreateByLocation("prog.cpp", 7);
I get same result
1.1: where = a.exe`doSomething() + 6 at prog.cpp:7, address = a.exe[0x00401356], unresolved, hit count = 0
My little research:
I compare lldb behavior in two versions:
Launch new process(is ok)
Attach to process(broken)
I found that in method
lldb::break_id_t
Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardware)
line..
load_addr = owner->GetAddress().GetOpcodeLoadAddress (&GetTarget());
return LLDB_INVALID_ADDRESS in version when I attach to process.
CallStack:
liblldb.dll!lldb_private::Process::CreateBreakpointSite(const std::shared_ptr<lldb_private::BreakpointLocation> & owner, bool use_hardware) Line 2094 C++
liblldb.dll!lldb_private::BreakpointLocation::ResolveBreakpointSite() Line 523 C++
liblldb.dll!lldb_private::BreakpointLocationList::AddLocation(const lldb_private::Address & addr, bool resolve_indirect_symbols, bool * new_location) Line 254 C++
liblldb.dll!lldb_private::Breakpoint::AddLocation(const lldb_private::Address & addr, bool * new_location) Line 102 C++
liblldb.dll!lldb_private::BreakpointResolver::AddLocation(lldb_private::Address loc_addr, bool * new_location) Line 214 C++
liblldb.dll!lldb_private::BreakpointResolver::SetSCMatchesByLine(lldb_private::SearchFilter & filter, lldb_private::SymbolContextList & sc_list, bool skip_prologue, const char * log_ident) Line 184 C++
liblldb.dll!lldb_private::BreakpointResolverFileLine::SearchCallback(lldb_private::SearchFilter & filter, lldb_private::SymbolContext & context, lldb_private::Address * addr, bool containing) Line 94 C++
liblldb.dll!lldb_private::SearchFilter::DoModuleIteration(const lldb_private::SymbolContext & context, lldb_private::Searcher & searcher) Line 190 C++
liblldb.dll!lldb_private::SearchFilter::Search(lldb_private::Searcher & searcher) Line 118 C++
liblldb.dll!lldb_private::BreakpointResolver::ResolveBreakpoint(lldb_private::SearchFilter & filter) Line 62 C++
liblldb.dll!lldb_private::Breakpoint::ResolveBreakpoint() Line 355 C++
liblldb.dll!lldb_private::Target::AddBreakpoint(std::shared_ptr<lldb_private::Breakpoint> bp_sp, bool internal) Line 695 C++
liblldb.dll!lldb_private::Target::CreateBreakpoint(std::shared_ptr<lldb_private::SearchFilter> & filter_sp, std::shared_ptr<lldb_private::BreakpointResolver> & resolver_sp, bool internal, bool request_hardware, bool resolve_indirect_symbols) Line 672 C++
liblldb.dll!lldb_private::Target::CreateBreakpoint(const lldb_private::FileSpecList * containingModules, const lldb_private::FileSpec & file, unsigned int line_no, unsigned __int64 offset, lldb_private::LazyBool check_inlines, lldb_private::LazyBool skip_prologue, bool internal, bool hardware, lldb_private::LazyBool move_to_nearest_code) Line 411 C++
liblldb.dll!lldb::SBTarget::BreakpointCreateByLocation(const lldb::SBFileSpec & sb_file_spec, unsigned int line, unsigned __int64 offset) Line 832 C++
liblldb.dll!lldb::SBTarget::BreakpointCreateByLocation(const lldb::SBFileSpec & sb_file_spec, unsigned int line) Line 803 C++
liblldb.dll!lldb::SBTarget::BreakpointCreateByLocation(const char * file, unsigned int line) Line 796 C++
ConsoleApplication1.exe!Debugger::LLDBRunner::setBreakpoint(std::basic_string<char,std::char_traits<char>,std::allocator<char> > file, unsigned int line) Line 204 C++
ConsoleApplication1.exe!main() Line 28 C++
UPDATE 2:
I print 'a.exe' module sections using the following code:
for (int i = 0; i < m_debugData->currentTarget.GetNumModules(); i++)
{
auto module = m_debugData->currentTarget.GetModuleAtIndex(i);
auto moduleName = module.GetFileSpec().GetFilename();
for (int j = 0; j < module.GetNumSections(); j++)
{
auto section = module.GetSectionAtIndex(j);
auto sectionName = section.GetName();
auto addr = section.GetLoadAddress(m_debugData->currentTarget);
auto isValid = LLDB_INVALID_ADDRESS != addr;
std::cout << "Module: " << moduleName << "; Section: " << sectionName << "; IsValid: " << isValid << std::endl;
}
}
An output was:
State changed unknown->stopped
Module: a.exe; Section: .text; IsValid: 0
Module: a.exe; Section: .data; IsValid: 0
Module: a.exe; Section: .rdata; IsValid: 0
Module: a.exe; Section: .eh_frame; IsValid: 0
Module: a.exe; Section: .bss; IsValid: 0
Module: a.exe; Section: .idata; IsValid: 0
Module: a.exe; Section: .CRT; IsValid: 0
Module: a.exe; Section: .tls; IsValid: 0
Module: a.exe; Section: .debug_aranges; IsValid: 0
Module: a.exe; Section: .debug_info; IsValid: 0
Module: a.exe; Section: .debug_abbrev; IsValid: 0
Module: a.exe; Section: .debug_line; IsValid: 0
Module: a.exe; Section: .debug_frame; IsValid: 0

It's hard to say with certainty, but the python APIs and the command line apis are not entirely the same. They both have their own set of things they do internally before running the "actual" command you requested. Debugging on Windows is definitely not as mature as on other platforms, in part because there are not a lot of people using it yet. I would suggest reporting this as a bug on the lldb bug tracker.
In the meantime, maybe you can try creating a target manually, and setting the breakpoint BEFORE you attach to the process. I don't know if this will work, but resolving a breakpoint dynamically when a module is loaded, versus trying to resolve it immediately when you drop the breakpoint down are two different codepaths, so it's possible it will work if the breakpoint is already there.

Related

Segmentation Fault in C++ With for Loop [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am making an Ant simulation with SDL2 and when I run my code it soon crashed giving me a segmentation fault. I believe this is from trying to access negative values in an array. I tried to make it so the Ant can't do this by giving an if statement checking its value on the "grid" I made out of squares. I added an if statement on line 420 to try and stop my theory but it didn't do anything. Does anyone see the issue here?
My Grid Initialiation:
struct Wall
{
bool IsAlive;
int Health = 10;
SDL_Rect Rect;
bool isAnt;
bool IsHome;
bool IsFood;
};
This is where I set up the rects:
int count = 0;
for (int i = 0; i < 1440; i += 4)
{
for (int j = 0; j < 795; j += 4)
{
SDL_Rect Rect = {i, j, 4, 4};
wall[count].Rect = Rect;
wall[count].IsAlive = true;
if (i < 10)
{
if (j < 10)
{
wall[count].IsAlive = false;
}
}
count++;
}
}
And this is where I do the Ant Digging:
void Break(int AntID, int SurroundingSqr /*Clockwise*/)
{
if (SurroundingSqr == -199)
{
if (A[AntID].PosID > 100)
{
wall[A[AntID].PosID + SurroundingSqr].Health--;
if (wall[A[AntID].PosID + SurroundingSqr].Health == 0)
{
wall[A[AntID].PosID + SurroundingSqr].IsAlive = false;
}
}
}
else
{
wall[A[AntID].PosID + SurroundingSqr].Health--;
if (wall[A[AntID].PosID + SurroundingSqr].Health == 0)
{
wall[A[AntID].PosID + SurroundingSqr].IsAlive = false;
}
}
}
If you want to see all the code you can go to this Gist
You should include all the headers you need. You are missing #include <ctime>.
You have undefined behavior because of indices running out of bounds, as can be seen when running your program compiled with -g -fsanitize=address,undefined:
ant.cpp:350:34: runtime error: index -199 out of bounds for type 'Wall [572397]'
ant.cpp:356:32: runtime error: index -1 out of bounds for type 'Wall [572397]'
=================================================================
==3989611==ERROR: AddressSanitizer: global-buffer-overflow on address 0x00000042fae4 at pc 0x000000405540 bp 0x7ffe896fa2e0 sp 0x7ffe896fa2d8
READ of size 1 at 0x00000042fae4 thread T0
#0 0x40553f in MoveLeft(int) /home/ted/proj/stackoverflow/ant.cpp:356
#1 0x407f87 in MakeAntActions() /home/ted/proj/stackoverflow/ant.cpp:213
#2 0x402687 in main /home/ted/proj/stackoverflow/ant.cpp:102
#3 0x7ff7a0671b74 in __libc_start_main (/lib64/libc.so.6+0x27b74)
#4 0x40293d in _start (/home/ted/proj/stackoverflow/ant-g+++0x40293d)
I would start nesting out the problem by following the call chain from line
102: MakeAntActions(); ➔
213: MoveLeft(i); ➔
350 and 356 (where it croaks)
if (wall[A[AntID].PosID - 199].IsAlive) // line 350 index -199
if (wall[A[AntID].PosID - 1].IsAlive) // line 356 index -1
So, A[AntID].PosID is 0 at the time the program reaches these lines which creates these negative indices - and negative indices are not allowed.
Compile with -g -fsanitize=address,undefined to get hints like this.

Value of class variable mysteriously changing

I have an Elf class which reads in Elf headers and constructs various data structures; I am using mmap and mmap the file to a variable maddr in the above class. A pointer to this class is passed to a DwarfSymTab class (which relies on a Dwarf class which does the basic read of dwarf sections) but in the constructor for this class, maddr has suddenly changed in value from when it was first initialized.
I am using dbx to watch this change, but dbx is complaining about a variable out of scope which is quite definitely defined in the class. Following are some extracts of the class definitions and the dbx output.
class Elf {
friend class DwarfSymTab;
friend class SymTab;
friend class Dwarf;
friend class HostFunc;
int fd;
ElfEhdr ehdr;
ElfEhdr *h;
uchar magic[4];
ElfSect *symtab;
ElfSect *symstr;
ElfSect *dynsym;
ElfSect *dynstr;
ElfSect *bss;
ulong dynamic;
struct stat st;
uchar *maddr;
. . .
};
class DwarfSymTab : public SymTab {
private:
Elf *elf;
Dwarf *dwarf;
DwarfRec *r;
DwarfUType *dt;
DwarfLine *dline;
MemLayout memlayout;
. . .
};
Localproc *HostFunc::coreopen(int corefd, int stabfd){
. . .
e[STAB] = new Elf();
if(e[STAB]->fdopen(stabfd) < 0){
fprintf(stderr, "Elf::open: %s\n", e[STAB]->perror());
exit(1);
}
stopped in HostFunc::coreopen at line 858 in file "hostfunc.cc"
858 e[CORE] = new Elf();
(dbx) print e[0], e[0]->maddr
e[0] = 0x81b26bc
e[0]->maddr = 0xfe6ce000 "^?ELF^A^A^A^F^A"
DwarfSymTab::DwarfSymTab(Core* c, Elf *e, SymTab *i, long reloc)
:SymTab(c, e, i, reloc) {
elf = e;
r = new DwarfRec;
}
stopped in DwarfSymTab::DwarfSymTab at line 30 in file "dwarfsymtab.cc"
30 elf = e;
(dbx) next
stopped in DwarfSymTab::DwarfSymTab at line 31 in file "dwarfsymtab.cc"
31 r = new DwarfRec;
(dbx) print e, e->maddr
e = 0x81b26bc
e->maddr = 0x69727473 "<bad address 0x69727473>"
(dbx) print elf
dbx: "elf" is not defined in the scope `pi`dwarfsymtab.cc`DwarfSymTab::DwarfSymTab(Core*,Elf*,SymTab*,long)`
(dbx) print e->fd
e->fd = 6
You can see that the pointer to the Elf class is in tact, and that maddr has been trashed in some way while for example, the fd member is fine (this is the fd of the file from which Elf data is being read ... I have omitted the dbx output showing this to be the case but it is so).
Can anyone explain what might be going on?
Postscript: I have tracked down the change in 'maddr' to a call to a function. This is how dbx shows it. I first stop in the following function, and I've arranged to pass the pointer to the Elf class as an argument:
void SymTab::read(Elf *e){
const char *error;
trace( "%d.read()", this ); VOK;
trace( "symtab modified %d", modtime() );
_root = 0;
if( error = gethdr(e) )
_warn = sf( "symbol table header: %s; go on", error );
stopped in SymTab::read at line 164 in file "symtab.cc"
164 trace( "%d.read()", this ); VOK;
(dbx) where
=>[1] SymTab::read(this = 0x81b757c, e = 0x81b25fc), line 164 in "symtab.cc"
[2] HostCore::open(this = 0x81b24a0), line 512 in "hostcore.cc"
[3] HostProcess::open(this = 0x81b1c24, ischild = 0), line 318 in "hostcore.cc"
[4] TermAction(parent = 0x818b294, obj = 0x81b1c24, pick = 0), line 160 in "term.cc"
[5] TermServe(), line 238 in "term.cc"
[6] PadsServe(n = 0), line 292 in "term.cc"
[7] main(argc = 1, av = 0xfeffdd68), line 75 in "pi.cc"
At this point, the pointer to the memory-mapped region is correct. The fd is that of the file from which elf sections are being read:
(dbx) print e, e->fd, e->maddr
e = 0x81b25fc
e->fd = 7
e->maddr = 0xfe6ce000 "^?ELF^A^A^A^F^A"
Stepping over a few instructions:
. . .
(dbx) next
stopped in SymTab::read at line 167 in file "symtab.cc"
167 if( error = gethdr(e) )
and then stepping into the routine which reads the dwarf structures:
(dbx) step
stopped in DwarfSymTab::gethdr at line 36 in file "dwarfsymtab.cc"
36 switch(elf->encoding()){
(dbx) where
=>[1] DwarfSymTab::gethdr(this = 0x81b757c, e = 0x81b25fc), line 36 in "dwarfsymtab.cc"
[2] SymTab::read(this = 0x81b757c, e = 0x81b25fc), line 167 in "symtab.cc"
[3] HostCore::open(this = 0x81b24a0), line 512 in "hostcore.cc"
[4] HostProcess::open(this = 0x81b1c24, ischild = 0), line 318 in "hostcore.cc"
[5] TermAction(parent = 0x818b294, obj = 0x81b1c24, pick = 0), line 160 in "term.cc"
[6] TermServe(), line 238 in "term.cc"
[7] PadsServe(n = 0), line 292 in "term.cc"
[8] main(argc = 1, av = 0xfeffdd68), line 75 in "pi.cc"
At this point, maddr has clearly been trampled on, but nothing else:
(dbx) print e, e->fd, e->maddr
e = 0x81b25fc
e->fd = 7
e->maddr = 0x69727473 "<bad address 0x69727473>"
Since there is no malloc'ing going on across a function call (as far as I know), what could be causing this? 'gethdr' in the DwarfSymTab class is overrinding a virtual function in the base 'SymTab' class. I don't know if this has any bearing on how the function is called.
I apologize for the amount of detail, but as I pointed out, the problem can't be really simplified (or perhaps it's beyond my abilities).
Post-postscript: In fact the situation is worse than this because of the following. It is true that by stepping into the 'gethdr' function as above, the 'maddr' member of the Elf class is incorrect, but if I go back down the stack to the calling frame, everything is fine:
(dbx) next
stopped in SymTab::read at line 167 in file "symtab.cc"
167 if( error = gethdr(e) )
(dbx) step
stopped in DwarfSymTab::gethdr at line 36 in file "dwarfsymtab.cc"
36 switch(elf->encoding()){
(dbx) print e, e->fd, e->maddr
e = 0x81b25fc
e->fd = 7
e->maddr = 0x69727473 "<bad address 0x69727473>"
(dbx) up
Current function is SymTab::read
167 if( error = gethdr(e) )
(dbx) print e, e->fd, e->maddr
e = 0x81b25fc
e->fd = 7
e->maddr = 0xfe6ce000 "^?ELF^A^A^A^F^A"
This simply doesn't make any sense to me.

LLVM,Fail to create call instruction by LLVM IRBuilder class

I want to write a simple frontend for language PL/0,the lexer and parser seems work well,but there has a bug when generating call statement LLVM IR.
Here is my code for generating IR for the PL/0 call statement: CALL ident. It fails to execute the Builder.CreateCall(F,None,"calltmp");
The console says:
pl0: /root/llvm-6.0/lib/IR/Value.cpp:247:
void llvm::Value::setNameImpl(const llvm::Twine&):
Assertion `!getType()->isVoidTy() && "Cannot assign a name to void values!"' failed.
Aborted (core dumped)
The TheModule->getFunction() gets the correct function. All functions in my implementation has function type void ..(), no return value and no argument.
I tried to debug it with gdb; it seems the instruction created by Builder.CreateCall(...) is "optimized out".
What's wrong with this?
Code for generating call statement:
bool CallStatAST::codegen()
{
auto F = TheModule->getFunction(Callee);
if(!F)
logErrorL("Failing to get function from module at CallStatAST::codegen()!\n");
//std::vector<Value*> Args;
Builder.CreateCall(F,None,"calltmp");
return true;
}
gdb debug information:
1. (gdb) break 391
Breakpoint 1 at 0x4713a5: file pl0.cpp, line 391.
2. (gdb) run < test1.pl0
Starting program: /root/my_llvm/PL0/pl0 < test1.pl0
3. Breakpoint 1, get (this=optimized out) at /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/unique_ptr.h:234
234 { return std::get<0>(_M_t); }
4. (gdb) n
CallStatAST::codegen (this=0xa165d0) at pl0.cpp:392
392 auto F = TheModule->getFunction(Callee);
5. (gdb) p F->dump()
define internal void #myfun()
{
entry:
%i = alloca double
%a = load double, double* #a
%b = load double, double* #b
%addtmp = fadd double %a, %b
store double %addtmp, double* %i
ret void
}
$1 = void
6. (gdb) p F->getName()
$2 = {static npos = 18446744073709551615, Data = 0xa17310 "myfun", Length = 5}
(gdb) n
397 Builder.CreateCall(F,None,"calltmp");
7. (gdb) s
Twine (Str=0xa17278 "\300P\241", this=optimized out) at /usr/local/include/llvm/ADT/Twine.h:270
270 LHS.cString = Str;
8. (gdb) n
CallStatAST::codegen (this=optimized out) at pl0.cpp:397
397 Builder.CreateCall(F,None,"calltmp");
How fool I am!
I unbelievable want to assign a name to a void return value,there does not have a value and how can set a name for it?
convert:
Builder.CreateCall(F,None,"calltmp");
to:
Builder.CreateCall(F,None);
all things work again!

Node.js: devided stdout using SPAWN with exe program

I wrote some C++ program which is waiting for 103 data strings and response on the output with 9 strings. I would like to send data from the node app and receive the data from the output. Unfortunately I found that the output data, that I display in the console, it is not from the same reading cycle.
So the question is: Does stdin and stdout in node app has any buffer which I can flush or something?
Here is my c++ program:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
cout << "Program is running";
vector <string> tab(103);
string nazwa;
int index = 0;
do {
for (int i = 0; i < 103; i++) {
getline(cin, nazwa);
if (!nazwa.empty() && nazwa[nazwa.size() - 1] == '\n')
nazwa.erase(nazwa.size() - 1);
if (!nazwa.empty() && nazwa[nazwa.size() - 1] == '\r')
nazwa.erase(nazwa.size() - 1);
tab[i] = nazwa;
}
for (int i = 0; i < 9; i++) {
cout << index << ": " << i+1 << endl;
}
index++;
} while (true);
return 0;
}
It simply wait for 103 strings with data from node and give back 9 stings.
Here is my node program:
var prg = null;
var str = "";
var counter = 0;
var spawn = require('child_process').spawn;
var fun = function(){
console.log("fun() start");
prg = spawn('test.exe');
};
fun();
setInterval(function() {
//console.log(".");
prg.stdin.write('0.5\n');
}, 10);
prg.stdout.on('data', function(data) {
str = data.toString(), lines = str.split(/(\r&\n)/g);
for (var i=0;i<lines.length; i++) {
console.log('node counter: '+counter+", passed data: "+lines[i]);
}
counter++;
});
The output in the node console proving that the output is divided:
fun() start
node counter: 0, passed data: Program is running
node counter: 1, passed data: 0: 1
0: 2
0: 3
0: 4
0: 5
0: 6
0: 7
node counter: 2, passed data: 0: 8
0: 9
node counter: 3, passed data: 1: 1
1: 2
1: 3
1: 4
1: 5
1: 6
1: 7
1: 8
1: 9
UPDATE:
I found 3 solutions. I had to pass data via IPC (Inter Process Communication) to avoid these standard in/out buffers.
Possible ways:
Nodejs Addons
Named pipe
Sockets communication
I used great git project JSON for Modern C++ to pass easy in use data container.
I created JSON structure and put it into the file. Now I can read this file and send it to the pipe. The main problem with pipes is that its hard to control databytes from the pipe. But if you use JSON for Modern C++ addon, you will know when you have all data.
Because in every pipe reading I wont know how many bytes I will send this time, so I created bigger buffer and after reading all data from pipe I just cut them and use JSON parser again.
After reading data (c++ side) Im preparing this data to send it back to node.
Node code:
var prg = null;
var fs = require('fs');
//parse JSON from file
var obj = JSON.parse(fs.readFileSync('data.json', 'utf8'));
var net = require('net');
var path = require('path');
var counter = 0;
//create pipe
var server = net.createServer(function(req) {
setInterval(function() {
var strobj = JSON.stringify(obj);
req.write(strobj); // send data to pipe every second
}, 1000);
rehttps://stackoverflow.com/questionsq.on('data', function(c) {
var size = c.length;
console.log(counter+': bytesize of JSON: ' + size);
var reciv = JSON.parse(c);
counter++;
console.log("Display JSON:\n %j ",reciv);
});
});
server.listen('\\\\.\\pipe\\JointsPipe');
// Spawning EXE program
var spawn = require('child_process').spawn;
var prg = spawn('test.exe');
prg.on('close', function(){
console.log("Pipe Closed");
});
C++ Program
I hope it will help someone.
I assume that node.js child_process.spawn creates a child process, which is sharing it's parents stdin, stdout and stderr streams. Since both the parent and the child are writing to those streams you'll get an 'intermixed' output. You can try to redirect each of those to different files and get not divided output. Or you could try to use some shared resource to communicate between the parent and the child process (eg. some socket or named pipe)

Exception 3 thrown during clear() or when destroying vectors

Description
Sometimes I get exception 3 when trying to clear() a std::vector.
Hardware
Hardware: ESP-07S
ESP8266-Arduino library core version: 2.4.0-rc1
Settings in IDE
Module: Generic ESP8266 Module
Flash Size: 4MB
CPU Frequency: 160Mhz
Flash Mode: qio
Flash Frequency: 40Mhz
Upload Using: OTA / SERIAL
Reset Method: ck
Stacktrace
This is stacktrace from Arduino's Exception Decoder:
Exception 3: LoadStoreError: Processor internal physical address or data error during load or store
Decoding 30 results
0x401000b7: umm_disconnect_from_free_list at C:\Users\Defozo\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc1\cores\esp8266\umm_malloc/umm_malloc.c line 1151
0x4021e9bc: memmove at /Users/igrokhotkov/e/newlib-xtensa/xtensa-lx106-elf/newlib/libc/string/../../../.././newlib/libc/string/memmove.c line 69 (discriminator 1)
0x40217464: Print::write(unsigned char const*, unsigned int) at C:\Users\Defozo\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc1\cores\esp8266/Print.cpp line 38
0x4010020c: _umm_free at C:\Users\Defozo\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc1\cores\esp8266\umm_malloc/umm_malloc.c line 1287
0x4010068c: free at C:\Users\Defozo\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc1\cores\esp8266\umm_malloc/umm_malloc.c line 1733
0x40215b04: operator delete(void*) at C:\Users\Defozo\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc1\cores\esp8266/abi.cpp line 57
0x40207940: std::_Vector_base >::_M_deallocate(double*, unsigned int) at C:\Users\Defozo\Documents\Arduino\jeszcze nowsza wersja laser_na_stacje_v2\laser_na_stacje_v2/laser_na_stacje_v2.ino line 565
0x402088ac: std::_Vector_base >::~_Vector_base() at c:\users\defozo\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits/stl_vector.h line 161
0x40209748: std::vector >::_M_erase_at_end(double*) at c:\users\defozo\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits/stl_vector.h line 1353
: (inlined by) std::vector >::clear() at c:\users\defozo\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits/stl_vector.h line 1126
: (inlined by) loop at C:\Users\Defozo\Documents\Arduino\jeszcze nowsza wersja laser_na_stacje_v2\laser_na_stacje_v2/laser_na_stacje_v2.ino line 412
0x40217082: std::default_delete ::operator()(TransportTraits*) const at c:\users\defozo\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits/unique_ptr.h line 68
0x4010020c: _umm_free at C:\Users\Defozo\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc1\cores\esp8266\umm_malloc/umm_malloc.c line 1287
0x401020ea: wDev_ProcessFiq at ?? line ?
0x40215d84: loop_wrapper at C:\Users\Defozo\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc1\cores\esp8266/core_esp8266_main.cpp line 124
0x4010070c: cont_norm at C:\Users\Defozo\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0-rc1\cores\esp8266/cont.S line 109
This is reset cause:
Hardware Watchdog
Fatal exception:4 flag:1 (WDT) epc1:0x40000f83 epc2:0x00000000 epc3:0x4000dd3b excvaddr:0x40023c5c depc:0x00000000
Code
I'm initializing vectors like that:
std::vector<double> dhtTempVector, dhtHumidityVector;
std::vector<double> dhtTempMedianVector, dhtHumidityMedianVector;
std::vector<double> bmpTempVector, bmpPressureVector;
std::vector<double> bmpTempMedianVector, bmpPressureMedianVector;
dhtTempVector.reserve(5);
dhtHumidityVector.reserve(5);
bmpTempVector.reserve(5);
bmpPressureVector.reserve(5);
dhtTempMedianVector.reserve(6);
dhtHumidityMedianVector.reserve(6);
bmpPressureMedianVector.reserve(6);
bmpTempMedianVector.reserve(6);
Inserting new values like that:
if (!isnan(temp) && !isnan(hum)) {
dhtTempVector.push_back(temp);
dhtHumidityVector.push_back(hum);
}
and:
if (!dhtTempVector.empty()) {
dhtTempMedianVector.push_back(median(dhtTempVector));
dhtTempVector.clear();
}
if (!dhtHumidityVector.empty()) {
dhtHumidityMedianVector.push_back(median(dhtHumidityVector));
dhtHumidityVector.clear(); //line number 412
}
This is the median function:
double median(std::vector<double> v)
{
size_t n = v.size() / 2;
std::nth_element(v.begin(), v.begin()+n, v.end());
double vn = v[n];
if(v.size()%2 == 1) {
return vn;
} else {
std::nth_element(v.begin(), v.begin()+n-1, v.end());
return 0.5*(vn+v[n-1]);
}
}
Additional debug information
This is a result:
dhtTempVector size: 4
dhtTempMedianVector size: 5
dhtHumidityVector size: 4
dhtHumidityMedianVector size: 5
29.00 29.00 29.00 29.00 --
28.70 28.75 28.80 28.90 28.90 --
41.20 41.30 41.80 41.40 --
42.65 42.55 41.80 42.30 41.75 --
of these lines of code:
Serial.print("dhtTempVector size: ");
Serial.println(dhtTempVector.size());
Serial.print("dhtTempMedianVector size: ");
Serial.println(dhtTempMedianVector.size());
Serial.print("dhtHumidityVector size: ");
Serial.println(dhtHumidityVector.size());
Serial.print("dhtHumidityMedianVector size: ");
Serial.println(dhtHumidityMedianVector.size());
for (int k = 0; k < dhtTempVector.size(); ++k) {
Serial.print(dhtTempVector.at(k));
Serial.print(" ");
}
Serial.println("--");
for (int k = 0; k < dhtTempMedianVector.size(); ++k) {
Serial.print(dhtTempMedianVector.at(k));
Serial.print(" ");
}
Serial.println("--");
for (int k = 0; k < dhtHumidityVector.size(); ++k) {
Serial.print(dhtHumidityVector.at(k));
Serial.print(" ");
}
Serial.println("--");
for (int k = 0; k < dhtHumidityMedianVector.size(); ++k) {
Serial.print(dhtHumidityMedianVector.at(k));
Serial.print(" ");
}
Serial.println("--");
just before the exception is thrown.
Summary
It looks like the exception is thrown during clearing the vector. I think I experienced exceptions thrown at the end of the loop() function too - so at the time when destructors of the vectors are fired. I'd think it's a problem with destroying the elements of the vectors but they're just double numbers.
What could be the problem?
#Edit
The Arduino-ESP8266 library that I'm using is available here:
https://github.com/esp8266
Here is umm_malloc.c:
https://github.com/esp8266/Arduino/blob/master/cores/esp8266/umm_malloc/umm_malloc.c
Print.cpp:
https://github.com/esp8266/Arduino/blob/4897e0006b5b0123a2fa31f67b14a3fff65ce561/cores/esp8266/Print.cpp
cont.S:
https://github.com/esp8266/Arduino/blob/4897e0006b5b0123a2fa31f67b14a3fff65ce561/cores/esp8266/cont.S
Specific lines from umm_malloc.c:
1151:
UMM_NFREE(UMM_PFREE(c)) = UMM_NFREE(c);
https://github.com/esp8266/Arduino/blob/master/cores/esp8266/umm_malloc/umm_malloc.c#L1151
1287:
if( UMM_NBLOCK(UMM_PBLOCK(c)) & UMM_FREELIST_MASK ) {
https://github.com/esp8266/Arduino/blob/master/cores/esp8266/umm_malloc/umm_malloc.c#L1287
1733:
void umm_free( void *ptr ) {
ptr = GET_UNPOISONED(ptr);
/* check poison of each blocks, if poisoning is enabled */
if (!CHECK_POISON_ALL_BLOCKS()) {
return;
}
/* check full integrity of the heap, if this check is enabled */
if (!INTEGRITY_CHECK()) {
return;
}
_umm_free( ptr );
} //1733
https://github.com/esp8266/Arduino/blob/master/cores/esp8266/umm_malloc/umm_malloc.c#L1733
Specific line from Print.cpp:
size_t Print::write(const uint8_t *buffer, size_t size) {
size_t n = 0;
while(size--) {
n += write(*buffer++); //line number 38
}
return n;
}
https://github.com/esp8266/Arduino/blob/4897e0006b5b0123a2fa31f67b14a3fff65ce561/cores/esp8266/Print.cpp#L38
Specific line from core_esp8266_main.cpp:
static void loop_wrapper() {
static bool setup_done = false;
preloop_update_frequency();
if(!setup_done) {
setup();
#ifdef DEBUG_ESP_PORT
DEBUG_ESP_PORT.setDebugOutput(true);
#endif
setup_done = true;
}
loop();
run_scheduled_functions(); //line number 124
esp_schedule();
}
Line number 109 from cont.S:
https://github.com/esp8266/Arduino/blob/4897e0006b5b0123a2fa31f67b14a3fff65ce561/cores/esp8266/cont.S#L109