我有一个不确定的内存损坏问题。因为它并不总是相同的地址,并且很少发生,所以我不能 while (my $line = <$fh>) {
chomp $line;
#remove square brackets
$line=~s/[\[\]]//;
while($line =~m/((\s*(.*))\/((.*)\s+))/gi)
{
$word=$1;
$tag=$2;
#remove whitespace from left and right of string
$word=~ s/^\s+|\s+$//g;
$tag=~ s/^\s+|\s+$//g;
$tags{$tag}++;
$tagHash{$tag}{$word}++;
}
}
foreach my $str (sort keys %tagHash)
{
foreach my $s (keys %{$tagHash{$str}} )
{
print "tags:$str - word: $s-> $tagHash{$str}{$s}\n";
}
}
watchpoint
。
问题是我的程序中A点和B点之间的值发生了变化。唯一应该改变它的是C点,它不会在那个时间运行(至少不会遇到意外修改的特定实例)。
我想做的事情就像gdb
点A处的值一样,如果它被修改并且在C点的故意修改周围再次受到保护,机器将陷入陷阱。当然,{ {1}}并不意味着字面意思,因为我需要它来处理单词粒度。
只需用mprotect
手动指向A点就太费力了,问题的频率只有千分之一左右。
理想情况下,我想在修改它的点上进行堆栈跟踪。
有什么想法吗?
更新:我刚刚发现mprotect
http://rr-project.org/,这个工具据称可以确定&#34;确定&#34;非决定论问题。我准备好了。
更新2:这是一次短途旅行:
gdb
答案 0 :(得分:3)
您遇到了未定义的行为,并且它正在其他地方引起,调试这非常困难。
由于您显然是在Linux上,请使用valgrind,它会对您有所帮助。如果您不在Linux或( OS X也受valgrind 支持),请为您的系统搜索等效的内存错误检测软件。
答案 1 :(得分:2)
我发现用你知道的脚本语言(在我的例子中,gdb
)编写Ruby
脚本并不困难。这减少了学习如何制作正确的gdb
脚本的需要!
目标程序和脚本之间的API是目标程序有一个名为my_breakpoint
的空白函数,它接受一个机器字作为参数。调用my_breakpoint(1); my_breakpoint(addr);
会在监视列表中添加一个地址,而常量2
的相同内容会从监视列表中删除一个地址。
要使用此功能,您需要启动gdbserver 127.0.0.1:7117 myapp myargs
,然后启动以下脚本。当脚本检测到问题时,它会与gdbserver
完全断开连接,以便您可以将gdb
的另一个实例与gdb -ex 'target remote 127.0.0.1:7117'
重新连接,然后离开。
请注意,使用此类软件观察点时,极其的速度很慢;也许有一天这样的东西可以作为valgrind工具来实现。
#!/usr/bin/env ruby
system("rm -f /tmp/gdb_i /tmp/gdb_o");
system("mkfifo /tmp/gdb_i /tmp/gdb_o");
system("killall -w gdb");
system("gdb -ex 'target remote 127.0.0.1:7117' </tmp/gdb_i >/tmp/gdb_o &");
$fo = File.open("/tmp/gdb_i", "wb");
$fi = File.open("/tmp/gdb_o", "rb");
def gdb_put(l)
$stderr.puts("gdb_out: #{l}");
$fo.write((l + "\n"));
$fo.flush;
end
gdb_put("b my_breakpoint");
gdb_put("set can-use-hw-watchpoints 0");
gdb_put("c");
$state = 0;
$watchpoint_ctr = 1; # start at 1 so the 1st watchpoint gets 2, etc. this is because the breakpoint gets 1.
$watchpoint_nr = {};
def gdb_got_my_breakpoint(x)
$stderr.puts("my_breakpoint #{x}");
if ((x == 1) || (x == 2))
raise if ($state != 0);
$state = x;
gdb_put("c");
else
if ($state == 1)
raise if ($watchpoint_nr[x].nil?.!);
$watchpoint_nr[x] = ($watchpoint_ctr += 1);
gdb_put("watch *#{x}");
elsif ($state == 2)
nr = $watchpoint_nr[x];
if (nr.nil?)
$stderr.puts("WARNING: ignoring delete request for watchpoint #{x} not previously established");
else
gdb_put("delete #{nr}");
$watchpoint_nr.delete(x);
end
end
$state = 0;
gdb_put("info breakpoints");
$stderr.puts("INFO: my current notion: #{$watchpoint_nr}");
gdb_put("c");
end
end
def gdb_got(l)
t = l.split;
if ((t[0] == "Breakpoint") && (t[2] == "my_breakpoint"))
gdb_got_my_breakpoint(t[3][3..-2].to_i);
end
if (l.start_with?("Program received signal ") || l.start_with?("Watchpoint "))
gdb_put("disconnect");
gdb_put("q");
sleep;
end
end
while (l = $fi.gets)
l = l.strip;
$stderr.puts("gdb_inp: #{l}");
gdb_got(l);
end