- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有以下代码(它读取进程虚拟内存并使用 libpcre 匹配一些字符串),它编译时没有错误,但是如果我用 -Wall
编译它,我会收到一些警告,我将在之后显示代码。
编译后的代码运行但崩溃,*** glibc detected *** ./readmempcreuniq: double free or corruption (fasttop): 0x097b9c80 ***
,我怀疑问题出在线上pcre_get_substring(page, vector, pairs, 0, &buff);
因为函数的第一个参数需要 'const char *'
但得到的是 'unsigned char *'
,我怎样才能让它正确?
#ifdef TARGET_64
// for 64bit target (see /proc/cpuinfo addr size virtual)
#define MEM_MAX (1ULL << 48)
#else
#define MEM_MAX (1ULL << 32)
#endif
#define _LARGEFILE64_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/ptrace.h>
#include <pcre.h>
#include <locale.h>
int main(int argc, char **argv)
{
if (argc < 2) {
printf("Usage: %s <pid>\n", argv[0]);
exit(1);
}
char buf[128];
int pid = atoi(argv[1]);
snprintf(buf, sizeof(buf), "/proc/%d/mem", pid);
int fd = open(buf, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "Error opening mem file: %m\n");
exit(1);
}
pcre *f;
pcre_extra *f_ext;
char *pattern = "([0-9]{20,22})";
const char *errstr;
int errchar;
int vector[50];
int vecsize = 50;
int pairs;
const char *buff;
const unsigned char *tables;
int a;
int count = 0;
const char **matches = NULL;
const char **more_matches;
char *loc = setlocale(LC_ALL, 0);
setlocale(LC_ALL, loc);
tables = pcre_maketables();
long ptret = ptrace(PTRACE_ATTACH, pid, 0, 0);
if (ptret == -1) {
fprintf(stderr, "Ptrace failed: %s\n", strerror(errno));
close(fd);
exit(1);
}
unsigned char page[4096];
unsigned long long offset = 0;
while (offset < MEM_MAX) {
lseek64(fd, offset, SEEK_SET);
ssize_t ret;
ret = read(fd, page, sizeof(page));
if (ret > 0) {
page[ret] = '\0';
if((f = pcre_compile(pattern, PCRE_CASELESS|PCRE_MULTILINE, &errstr, &errchar, tables)) == NULL)
{
printf("Error: %s\nCharacter N%i\nPattern:%s\n", errstr, errchar, pattern);
}
else
{
f_ext = pcre_study(f, 0, &errstr);
a = 0;
while((pairs = pcre_exec(f, f_ext, page, sizeof(page), a, PCRE_NOTEMPTY, vector, vecsize)) >=0)
{
pcre_get_substring(page, vector, pairs, 0, &buff);
//printf("%s\n", buff);
more_matches = realloc(matches, (count+1)* sizeof(*more_matches));
if (more_matches!=NULL)
{
matches=more_matches;
matches[count++]=buff;
}
else
{
free(matches);
puts("Error (re)allocating memory");
exit(1);
}
a = vector[1] + 1;
}
int matches_len = count;
const char *uniques[matches_len];
int uniques_len = 0;
int already_exists;
int i, j;
for (i = 0; i < matches_len; i++)
{
already_exists = 0;
for ( j = 0; j < uniques_len; j++)
{
if (!strcmp(matches[i], uniques[j]))
{
already_exists = 1;
break;
}
}
if (!already_exists)
{
uniques[uniques_len] = matches[i];
uniques_len++;
}
}
for (i = 0; i < uniques_len; i++)
{
printf("%s\n", uniques[i]);
}
free(matches);
pcre_free(f);
}
}
offset += sizeof(page);
}
ptrace(PTRACE_DETACH, pid, 0, 0);
close(fd);
return 0;
}
错误:
xtmtrx@server:~/regex/proc$ ./readmempcreuniq 5663
92991999918876543209
99299299292663552673
111992229922222288
119988922220000077
*** glibc detected *** ./readmempcreuniq: double free or corruption (fasttop): 0x097b9c80 ***
======= Backtrace: =========
/lib/libc.so.6(+0x6c0c1)[0xb7dfa0c1]
/lib/libc.so.6(+0x6d930)[0xb7dfb930]
/lib/libc.so.6(+0x71681)[0xb7dff681]
/lib/libc.so.6(realloc+0xe3)[0xb7dffb13]
./readmempcreuniq[0x8048c86]
/lib/libc.so.6(__libc_start_main+0xe7)[0xb7da4ce7]
./readmempcreuniq[0x80488b1]
======= Memory map: ========
08048000-0804a000 r-xp 00000000 fd:01 68388533 /root/regex/proc/readmempcreuniq
0804a000-0804b000 r--p 00001000 fd:01 68388533 /root/regex/proc/readmempcreuniq
0804b000-0804c000 rw-p 00002000 fd:01 68388533 /root/regex/proc/readmempcreuniq
097a1000-097c2000 rw-p 097a1000 00:00 0 [heap]
b7c00000-b7c21000 rw-p b7c00000 00:00 0
b7c21000-b7d00000 ---p b7c21000 00:00 0
b7d66000-b7d80000 r-xp 00000000 fd:01 65901968 /lib/libgcc_s.so.1
b7d80000-b7d81000 r--p 00019000 fd:01 65901968 /lib/libgcc_s.so.1
b7d81000-b7d82000 rw-p 0001a000 fd:01 65901968 /lib/libgcc_s.so.1
b7d8c000-b7d8e000 rw-p b7d8c000 00:00 0
b7d8e000-b7ee5000 r-xp 00000000 fd:01 65901949 /lib/libc-2.12.1.so
b7ee5000-b7ee7000 r--p 00157000 fd:01 65901949 /lib/libc-2.12.1.so
b7ee7000-b7ee8000 rw-p 00159000 fd:01 65901949 /lib/libc-2.12.1.so
b7ee8000-b7eeb000 rw-p b7ee8000 00:00 0
b7eeb000-b7f1e000 r-xp 00000000 fd:01 65901993 /lib/libpcre.so.3.12.1
b7f1e000-b7f1f000 r--p 00032000 fd:01 65901993 /lib/libpcre.so.3.12.1
b7f1f000-b7f20000 rw-p 00033000 fd:01 65901993 /lib/libpcre.so.3.12.1
b7f29000-b7f2c000 rw-p b7f29000 00:00 0
b7f2c000-b7f48000 r-xp 00000000 fd:01 65901940 /lib/ld-2.12.1.so
b7f48000-b7f49000 r--p 0001b000 fd:01 65901940 /lib/ld-2.12.1.so
b7f49000-b7f4a000 rw-p 0001c000 fd:01 65901940 /lib/ld-2.12.1.so
bf8c1000-bf8d6000 rw-p 7ffffffe9000 00:00 0 [stack]
Aborted
使用 -Wall
开关编译代码的警告:
xtmtrx@server:~/regex/proc$ gcc -o readmempcreuniq readmempcreuniq.c -lpcre -Wall readmempcreuniq.c: In function 'main': readmempcreuniq.c:83: warning: pointer targets in passing argument 3 of 'pcre_exec' differ in signedness /usr/include/pcre.h:286: note: expected 'const char *' but argument is of type 'unsigned char *' readmempcreuniq.c:85: warning: pointer targets in passing argument 1 of 'pcre_get_substring' differ in signedness /usr/include/pcre.h:297: note: expected 'const char *' but argument is of type 'unsigned char *'
编辑:
根据@stdcall 提示,我使用 efence
编译程序,然后在核心转储上使用 GDB:
xtmtrx@server:~/regex/proc$ ./readmempcreuniq 6036
Electric Fence 2.1 Copyright (C) 1987-1998 Bruce Perens.
5,
Segmentation fault (core dumped)
xtmtrx@server:~/regex/proc$ gdb ./readmempcreuniq core
GNU gdb (GDB) 7.2-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/regex/proc/readmempcreuniq...done.
[New Thread 6093]
Reading symbols from /lib/libpcre.so.3...(no debugging symbols found)...done.
Loaded symbols for /lib/libpcre.so.3
Reading symbols from /usr/lib/libefence.so.0...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/libefence.so.0
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/libpthread.so.0...(no debugging symbols found)...done.
Loaded symbols for /lib/libpthread.so.0
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./readmempcreuniq 6036'.
Program terminated with signal 11, Segmentation fault.
#0 0x08048ef8 in main (argc=2, argv=0xbfe1d2d4) at readmempcreuniq.c:125
125 uniques[uniques_len] = matches[i];
看来@alk 是对的,问题出在 uniques[uniques_len] = matches[i];
新编辑:
根据@alk 提示,我更改了行:
for ( j = 0; j < uniques_len; j++)
到:
for ( j = 0; j < matches_len; j++)
现在段错误在别处:
Program terminated with signal 11, Segmentation fault.
#0 0x08048ea7 in main (argc=2, argv=0xbfaaa3e4) at readmempcreuniq.c:118
118 if (!strcmp(matches[i], uniques[j]))
最佳答案
在循环的下一轮之前 free()
之后,您永远不会将 matches
重置为 NULL
。因此,它在第一轮重新分配后仍保留原始值。
要么在进入内部处理循环之前将其设置为 NULL
(在第一遍时冗余),要么将其返回设置为 NULL
在 free(matches)
之后立即执行。或者,您可以简单地将其设置为具有初始 NULL
值的下一个外部循环的包含范围,但前面提到的更改是我能想到的最小的更改。
示例
matches = NULL; // HERE
while((pairs = pcre_exec(f, f_ext, page, sizeof(page), a, PCRE_NOTEMPTY, vector, vecsize)) >=0)
{
pcre_get_substring(page, vector, pairs, 0, &buff);
//printf("%s\n", buff);
more_matches = realloc(matches, (count+1)* sizeof(*more_matches));
if (more_matches!=NULL)
{
matches=more_matches;
matches[count++]=buff;
}
else
{
free(matches);
puts("Error (re)allocating memory");
exit(1);
}
a = vector[1] + 1;
}
或者……
for (i = 0; i < uniques_len; i++)
{
printf("%s\n", uniques[i]);
}
free(matches);
matches = NULL; // or HERE
pcre_free(f);
更多内容
继续我所注意到的事情:
这个:
ssize_t ret;
ret = read(fd, page, sizeof(page));
if (ret > 0) {
page[ret] = '\0';
似乎试图设置一个空字符终止符。如果是这样,您将在填充满的缓冲区上调用未定义的行为。应该是这样的:
ssize_t ret = read(fd, page, sizeof(page)-1); // NOTE SPACE FOR TERM
if (ret > 0) {
page[ret] = 0;
如果缓冲区的大小是特定的(你选择 4K 是有原因的)它应该是 4097 以确保最大精确的 4K 缓冲区。
还有一个……
您正在阅读的页面,我不能声称它是或不需要像我之前在代码中显示的那样被终止。但是假设它是并且你做了我建议的(或者.. 没有),这看起来也是错误的:
while((pairs = pcre_exec(f, f_ext, page, sizeof(page), a, PCRE_NOTEMPTY, vector, vecsize)) >=0)
这里你传递的是整个缓冲区的大小; 不是您读取的实际数据的大小。我是第一个告诉你我不熟悉 API 的人,但我很确定这应该是:
// notice the length of the buffer passed, ret
while((pairs = pcre_exec(f, f_ext, page, ret, a, PCRE_NOTEMPTY, vector, vecsize)) >=0)
换句话说,在读取数据量过小时,您是在告诉它数据比实际长度要长。同样,我对他们的 API 很天真,但这似乎是合理的。
独特匹配...
希望更容易阅读。
int matches_len = count, uniques_len = 0;
int i = 0, j = 0;
const char *uniques[matches_len];
for (i=0; i < matches_len; ++i)
{
for (j = 0; j < uniques_len; ++j)
{
if (!strcmp(matches[i], uniques[j]))
break;
}
if (j == uniques_len)
uniques[uniques_len++] = matches[i];
}
for (i = 0; i < uniques_len; ++i)
printf("%s\n", uniques[i]);
继续...
在每页之后将 count
重置为零。在 free(matches) 之后; matches = NULL;
会是个好地方。
值得注意。一旦文件读取开始失败,您的外循环中就没有退出案例,因此文件上会有很多砰砰声,无法超出其结尾。直到达到限制器计数。
最后的想法
我认为这与您想要做的很接近:
#define _LARGEFILE64_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/ptrace.h>
#include <pcre.h>
#include <locale.h>
#include <ctype.h>
int main(int argc, char **argv)
{
// CHANGE TO ACCEPT PROC-ID FROM CMDLINE
int pid = 5916;
setlocale(LC_ALL,"");
const char *error = NULL;
int erroffset = 0;
const char **uniques = NULL;
size_t uniques_len = 0;
const char regex[] = "[0-9A-Fa-f]{8}";
pcre* re = pcre_compile (regex, /* the pattern */
PCRE_MULTILINE|PCRE_DOTALL|PCRE_NEWLINE_ANYCRLF,
&error, /* for error message */
&erroffset, /* for error offset */
0); /* use default character tables */
if (!re)
{
printf("pcre_compile failed (offset: %d), %s\n", erroffset, error);
return -1;
}
// start proc trace
long ptret = ptrace(PTRACE_ATTACH, pid, 0, 0);
if (ptret == -1)
{
fprintf(stderr, "Ptrace failed: %s\n", strerror(errno));
exit(1);
}
char path[256];
snprintf(path, sizeof(path), "/proc/%d/maps", pid);
FILE *maps = fopen(path, "r");
snprintf(path, sizeof(path), "/proc/%d/mem", pid);
int mem = open(path, O_RDONLY);
if(maps && (mem != -1))
{
char buf[BUFSIZ + 1];
while(fgets(buf, BUFSIZ, maps))
{
long long unsigned int start, end;
if (sscanf(buf, "%llx-%llx", &start, &end) != 2)
break;
printf("reading %llx - %llx\n", start, end);
lseek64(mem, start, SEEK_SET);
while (start < end)
{
char page[4096] = {0};
int rd = read(mem, page, sizeof(page));
if (rd < 0)
break;
start += sizeof(page);
int ov[128] = {0};
unsigned int ov_len = 0;
int rc = 0;
while ((rc = pcre_exec(re, 0, page, (int)(rd), ov_len, 0, ov, 128)) >= 0)
{
int i = 0;
for(; i < rc; ++i)
{
const char *sp = NULL;
pcre_get_substring(page, ov, rc, i, &sp);
// search unique list
size_t j=0;
for (;j<uniques_len;++j)
{
if (!strcmp(sp, uniques[j]))
break;
}
if (uniques_len == j)
{
const char **tmp = realloc(uniques, (uniques_len+1)*sizeof(*uniques));
if (tmp == NULL)
{
perror("Failed to resize uniques.");
pcre_free_substring(sp);
}
else
{
uniques = tmp;
uniques[uniques_len++] = sp;
}
}
else
{ // delete string. not needed
pcre_free_substring(sp);
}
}
ov_len = ov[2*(rc-1)]+1;
}
}
}
fclose(maps);
close(mem);
}
size_t n = 0;
for (; n<uniques_len; ++n)
{
printf("%s\n", uniques[n]);
pcre_free_substring(uniques[n]);
}
printf("total uniques: %lu\n", uniques_len);
free(uniques);
ptrace(PTRACE_DETACH, pid, 0, 0);
return 0;
}
警告。我对这个 API 了解零,但我在这里看到并在线简要回顾了一些内容。 YMMV UAYOR。但似乎你一直都拥有它。只是累积独立于页面的唯一值(我认为这仍然是一个问题,页面边界,但那是另一天)。
关于c - Linux POSIX C LibPCRE `double free or corruption (fasttop)` 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21657732/
下面的代码有效,我觉得double(double)和double(*)(double)没有区别,square和 &square,我说得对吗? #include double square(doubl
我知道我的作业很草率,这是我在这门课上的第 4 次作业。任何帮助将不胜感激,谢谢。 double getPrincipal(0); double getRate(0); double getYe
我遇到了那个错误,当我使用类时,我在使用函数指针时遇到了这个错误。我的函数'ope'函数我该如何解决 evaluator::function(){ double (*ope) (dou
问题://故事从哪里开始 Graphics 类型中的方法 drawLine(int, int, int, int) 不适用于参数 (double, double, double, double) g.
我有一张 map> m1 形式的 map .我可以将其复制到 map m2 形式的 map 吗?这样键是相同的,并且 m2 中的值是 get(m1->second) 不使用循环?谢谢! 最佳答案 这样
有没有办法获取vector> 的“.first”和“.second”的连续内存? ?我的意思是: void func(int N, double* x, double* y) { for (i
我正在尝试将自定义 lambda 传递给需要函数指针的函数(更准确地说是 zero 中的 Brent library 函数)。 我的想法是,我将使用参数创建一次 lambda,然后用多个值对其求值 x
这是一个很简单的问题,让我很困惑。 我收到一个源文件的以下错误,但另一个没有: 4 src/Source2.cpp:1466: error: no matching function for cal
struct CalculatorBrain { private var accumulator: Double? func changeSign(operand: Double) -
在我正在进行的项目中,我尝试使用 curlpp库来发出一个简单的 html GET 请求。当我将 cpp 文件传递给 g++ 时,出现以下错误: /usr/local/include/curlpp
不使用double就能获得quadruple精度超过16位的数字吗?如果可能的话,这取决于编译器还是其他?因为我知道有人说他使用double精度,并且具有22位精度。 最佳答案 数据类型double
我正在寻找有关特斯拉 GPU 中硬件如何实现 double 的信息。我读到,两个流处理器正在处理单个 double 值,但我没有找到 nvidia 的任何官方论文。 提前致谢。聚苯硫醚为什么大多数 G
这个问题在这里已经有了答案: Passing capturing lambda as function pointer (10 个答案) 关闭 2 年前。 我有这个错误 error: cannot
情况:我有一个元组列表,其中添加了一个元组: List> list = new List>(); list .Add(new Tuple(2.2, 6.6)); 一切似乎都还好。但是......在 D
我有一个 JList,里面有一堆名字,还有一个包含这些名字值的数组 final Double[] filmcost = { 5.00, 5.50, 7.00, 6.00, 5.00 }; 我想做的是,
我试图找出牛顿法来求方程的根。这个错误出来了,我无法处理。 double fn(double n){ return sin(n)+log(n)-1; } double f1n(double n
我有一个 junit 测试断言两个 Double 对象,具有以下内容: Assert.assertEquals(Double expected, Double result); 这很好,然后我决定将其
我正在尝试引入部分数据文件来填充数组,用户尝试了三次输入正确的数据文件名。我一再遇到这些错误。我知道像 arr 这样的数组只是一个指向内存块的指针。 #include #include #incl
我正在尝试完成复习题(为即将到来的编程决赛),但是,我无法解决这个问题,因为我不断收到错误(标题)。正如预期的那样,我将发布问题和我尝试的解决方案。 问题: 给定以下函数定义:void swap(do
任何人都知道如何实现这一目标。我已经尝试了通常的公式,但我只得到正数 Double.NEGATIVE_INFINITY) return d; } } 这将以相同的概率
我是一名优秀的程序员,十分优秀!