我不喜欢在这里转储大量代码并要求人们为我调试,但我对C有点缺乏经验而且我完全难过了。
总体目标是在非常大的日志文件(11G +)上进行一些清理,我一次读取2048字节,然后扫描各行,将它们写入输出文件。我最初使用strstr来查找行结尾,但是我发现这不适用于读取缓冲区末尾的部分行 - 我认为这是因为我从文件中读取的“字符串”没有a \ 0在它结束时,strstr感到困惑。
所以,经过一段谷歌搜索后,我想我会尝试memmem,这似乎是strstr的“二进制安全”替代品。这就是我被困住的地方,我的程序在调用memmem期间是segfaulting。
#include <stdio.h>
#include <string.h>
#define BUFF_LEN 2048
int main (void)
{
char file_buff[BUFF_LEN], prev_line[BUFF_LEN], curr_line[BUFF_LEN];
char *p_line_start, *p_lf;
int bytes_consumed, bytes_read;
FILE *in_fp, *out_fp;
in_fp = fopen("208.log", "r");
out_fp = fopen("expanded.log", "w+");
int sane = 0;
while (1) {
bytes_read = fread(file_buff, 1, BUFF_LEN, in_fp);
if (bytes_read == 0) {
break;
}
// Set the pointer to the beginning of the file buffer
p_line_start = file_buff;
bytes_consumed = 0;
// Chomp lines
while (bytes_consumed < bytes_read) {
printf("Read to go with bytes_read = %d, bytes_consumed = %d\n",
bytes_read, bytes_consumed);
p_lf = (char *) memmem(p_line_start, bytes_read - bytes_consumed,
"\n", 1);
if (p_lf == NULL) {
// No newline left in file_buff, store what's left in
// curr_line and break out to read more from the file.
printf("At loop exit I have chomped %ld of %d\n",
p_line_start - file_buff, bytes_read);
//break;
goto cleanup;
}
// Copy the line to our current line buffer (including the newline)
memcpy(curr_line, p_line_start, p_lf - p_line_start + 1);
printf("Chomped a line of length %ld\n", p_lf - p_line_start + 1);
fwrite(curr_line, 1, p_lf - p_line_start + 1, out_fp);
p_line_start = p_lf + 1;
bytes_consumed += p_lf - p_line_start + 1;
}
有人可以在这里给我打电话吗?!
关于如何更好地为自己调试这个的提示也是受欢迎的。
答案 0 :(得分:2)
您的一条评论:
我投出了返回值,因为gcc正在发出警告: &#34;警告:赋值从整数中生成指针而不使用强制转换&#34;。
您只是通过转换返回值来隐藏问题。
memmem 会返回一个指针。通常今天指针是64位。如果您还没有声明该函数,编译器不会知道它返回一个指针,而是假设它返回一个整数。通常今天整数是32位。生成的代码将查找返回该整数的位置,并从那里获取32位。实际得到的是一半返回的指针。
尝试在调用memmem之后添加此行,并在声明或不声明memmem时查看打印输出是否有所不同:
printf("[p_lf = %p]\n", (void*)p_lf);
当我使用原始程序(没有声明)运行它时,它打印0xffffffffffffda67,然后崩溃,因为那是一个无效的指针。通过声明(使用#define _GNU_SOURCE),它打印了0x7fffffffda67,并没有崩溃。 请注意,如果仅使用0x7ffffffda67的32位低位,则获得0xffffda67,如果将其扩展为64位,则会获得0xffffffffffffda67,即原始程序的指针。 (地址空间布局随机化已关闭。)
这就是为什么你不应该投出回报值。