LINUX.ORG.RU

С, причина сегфолта.

 ,


0

1

Нужно прожку написать, которая из лог файла выводила статистику сканирования портов по секундно, каждой минуты.

вот файл: http://pastebin.com/SGiBnszW

вот код: почему после вызова add происходит сегфолт?

// #3 log file
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>

struct scan // Информация о сканировании в течении одной минуты
{
	char hr; // Час
	char mn; // Минута
	char qty[60];// Количество сканирований в каждую секунду
	struct scan* next;
};

typedef struct scan Scan;

void foll(FILE* f, char lim)//Бежим по файлу до символа lim(пропуск)
{
	if (getc(f) == lim)
		return;
	foll(f,lim);
}

char dtcd[8] = "Detected";
char prt[4] = "Port";
char scn[4] = "Scan";

char d[8];
char p[4];
char s[4];

char check()
{
	char res = 1;
	for(int i=4; i<8; i++)
		res = res & (d[i] == dtcd[i]);
	for(int i=0; i<4; i++)
	{
		res = res & (d[i] == dtcd[i]) & (p[i] == prt[i]) & (s[i] == scn[i]);
	}
	return res;
}

Scan* head;

void printLine(char q[])
{
	printf("sec qty\n");
	for(int i=0; i<60; i++)
	{
		if (q[i] != 0)
			printf("%3d %3d\n",i,q[i]);
	}
}

void add(int h, int m, int s)
{
	char flag = 1;
	if (head)
	{
		if ((head -> hr == h) & (head -> mn == m))
		{
			((head -> qty)[s]) += 1;
			flag = 0;
		}
	}
	if (flag)
	{
		Scan* tmp = calloc(1,sizeof(Scan));
		tmp -> hr = h;
		tmp -> mn = m;
		tmp -> qty[s] = 1;
		tmp -> next = head;
		head = tmp;
	}
	printf("get One %d %d:\n",h,m);
	printLine(head -> qty);
	getchar();
}

void delList(Scan* s)
{
	if (s == 0)
		return;
	delList(s -> next);
	free(s);
}

void show()
{
	printf("show one more or quit?(s,q): ");
	if (getchar() == 'q')
		return;
	printf("input hour and minute to show(h m): ");
	int h,m;
	scanf("%d %d",&h,&m);
	for(Scan* s=head; s!=0; s = s -> next)
	{
		if ((s -> hr == h) & (s -> mn == m))
		{
			printLine(s -> qty);
			show();
			return;
		}
	}
	printf("there is not scans at this time\n");
	show();
}

int main()
{
	char path[50];
	printf("input filename: ");
	scanf("%s",path);
	FILE* f = fopen(path,"rt");
	if (f == 0) // Если файл не открылся
	{
		printf("can't open\n");
		return 1;
	}
	fseek(f,0,SEEK_END);
	long long endP = ftell(f);
	fseek(f,0,SEEK_SET);
	head = 0;
	int th;
	int tm;
	int ts;
	printf("scanning file...");
	while (ftell(f) != endP)
	{
		foll(f,' ');
		foll(f,' ');
		foll(f,' ');
		fscanf(f,"%d:%d:%d",&th,&tm,&ts);
		foll(f,']');
		foll(f,']');
		fscanf(f,"%s %s %s",d,p,s);
		if (check())
		{
			add(th,tm,ts);
		}
		foll(f,'\n');
	}
	printf(" Ok\n");
//	show();
	delList(head);
	return 0;
}
★★★★★

Особо в подробности не вдавался, но может это быть из-за использования в foll рекурсии? Банально стек переполняется.

ssvda
()

Первое, что бросилось в глаза:

char dtcd[8] = «Detected»; char prt[4] = «Port»; char scn[4] = «Scan»; а где место для '\0' ?

char dtcd[9] = «Detected»; char prt[5] = «Port»; char scn[5] = «Scan»;

yandzee
()

Тоже в код не вникал... в функции add перед строчкой printLine(head -> qty); нет проверки на head == 0

nozh
()
Ответ на: комментарий от yandzee

check работает, отдельно проврял

Aswed ★★★★★
() автор топика
Ответ на: комментарий от nozh

к этому моменту head не может быть равно нулю. Да и пробовал проверку эту.

Aswed ★★★★★
() автор топика
char dtcd[8] = "Detected";
char prt[4] = "Port";
char scn[4] = "Scan";

Ви таки серьезно? Алсо, use gdb, Luke!

grouzen ★★
()
Ответ на: комментарий от lazyklimm

программа работет если add убрать, т.е. в foll и check ошибок нет вот gdb написал:

Program received signal SIGSEGV, Segmentation fault.
0x0804878e in add (h=10, m=51, s=9) at tmp.c:61
61			if ((head -> hr == h) & (head -> mn == m))
до этой строчки есть проверка head на NULL, так почему не работает?

Aswed ★★★★★
() автор топика
Ответ на: комментарий от lazyklimm

да, пропустил этот момент, но сейчас причина падение не он, ибо без add код работает

Aswed ★★★★★
() автор топика

Немного не в тему...

#!/bin/bash

FILE=$1

min_list=`cut -d" " -f8 $FILE | cut -d: -f1,2 | uniq`

for min in $min_list; do
  nscans=`grep $min $FILE | grep "drop it" | wc -l`
  echo "$min: $nscans"
done

backbone ★★★★★
()
Ответ на: комментарий от backbone

это хорошо, но мне надо на С

Aswed ★★★★★
() автор топика
Ответ на: комментарий от anonymous

qty - количество сканирований в каждую секунду. здесь в секунду s увеличивается количество сканирований на 1

Aswed ★★★★★
() автор топика

мда...

char check()
{
	char res = 1;
	for(int i=4; i<8; i++)
		res = res & (d[i] == dtcd[i]);
дальше не смотрел

anonymous
()

а вообще - ты с этим foll придумал какую-то хрень.

Кто мешал заюзать getline/strstr/scanf, например?

lazyklimm ★★★★★
()

Зачем здесь рекурсия, когда можно сделать гораздо проще.

yandzee
()

void foll(FILE* f, char lim)//Бежим по файлу до символа lim(пропуск) { while (res = getc(f) != lim && res != EOF) foll(f,lim); } Парень, перепиши, плиз, эту функцию:

void foll(FILE* f, char lim)//Бежим по файлу до символа lim(пропуск)
{
	if (getc(f) == lim)
		return;
	foll(f,lim);
}
ибо это ужасно. Си и рекурсивные вызовы не совместимы. Не в такой ситуации. Используй циклы:
void foll(FILE* f, char lim)//Бежим по файлу до символа lim(пропуск)
{
        int res;
        while (res = getc(f) != lim && res != EOF)
		foll(f,lim);
}
или как-то так.

delete83 ★★
()

Во-вторых, вместо

char dtcd[8] = "Detected";
char prt[4] = "Port";
char scn[4] = "Scan";
лучше будет написать
char dtcd[] = "Detected";
char prt[] = "Port";
char scn[] = "Scan";
Так ты хотя бы сам себе яйца не отстрелишь...

delete83 ★★
()

тред не читай сразу(топик+время) отвечай:
для начало поставь асерт(или ещё как ) перед:

((head -> qty)[s]) += 1;
в add на предмет s .(могет он <0 или >59)

так как в си сокращёное вычисление булевых у тебя flag запутывает логику:

if (head && ((head -> hr == h) & (head -> mn == m)){
			((head -> qty)[s]) += 1;
}else	{
		Scan* tmp = calloc(1,sizeof(Scan));
		tmp -> hr = h;
		tmp -> mn = m;
		tmp -> qty[s] = 1;
		tmp -> next = head;
		head = tmp;
}

qulinxao ★★☆
()

что понятней : [vr]

 ((head -> qty)[s]) += 1;
или
 *(head->qty+s)+=1
или
(head -> qty)[s] += 1;
?

зы. унарные всегда приоритет выше (би/тер)нарных

qulinxao ★★☆
()

fscanf(f,«%d:%d:%d»,&th,&tm,&ts) и fscanf(f,«%s %s %s»,d,p,s) следует проверять на код возврата (обе должны возвращать 3, иначе пора завершать работу программы). По хорошему, надо еще и принятые значения проверять на корректность.

delete83 ★★
()
char check()
{
	char res = 1;
	for(int i=4; i<8; i++)
		res = res & (d[i] == dtcd[i]);
	for(int i=0; i<4; i++)
	{
		res = res & (d[i] == dtcd[i]) & (p[i] == prt[i]) & (s[i] == scn[i]);
	}
	return res;
}

Убейте меня кто-нибудь... Я не могу, мне плохо.

delete83 ★★
()
Ответ на: комментарий от qulinxao

за сокращенные булевые спасибо, а результат так же сегфолт

Aswed ★★★★★
() автор топика
Ответ на: комментарий от delete83

Убейте меня кто-нибудь... Я не могу, мне плохо.

ну да, это же детектор-тред :)

anonymous
()
Ответ на: комментарий от Aswed

если не трудно в апдэйт старта выкати работающую без списка.

qulinxao ★★☆
()
Ответ на: комментарий от delete83

Убейте меня кто-нибудь... Я не могу, мне плохо.

Классический индусский код!!!

На нормальном C лучше делать strstr(fileline, «Detected Port Scan»).

sergv
()
Ответ на: комментарий от sergv

в ' std ' strstr могут быть баги и пока чел не заглянул в реализацию strstr (о которой он возможно и не знал) разве можно не самому писать?

qulinxao ★★☆
()
Ответ на: комментарий от qulinxao

Ну вот я и пишу «индусский код», раздел «велосипедостроительство». ;-)

sergv
()
Ответ на: комментарий от qulinxao

Я примерно так же на первом курсе рассуждал, за что меня препод по ИВТ (или как оно там называлось, где программировать нас учили) ругала за это постоянно.

delete83 ★★
()
Ответ на: комментарий от delete83

за конкретней что ругала мама-воспитательница-учительница?

за незнание наличия стандартной библиотеки Си?

за незнание функции из этой библиотеки?

вас там на первом курсе чему учили ? программированию или магическому девайсу IDE Borlаnd CBuilder?

для решения на вот код и он работает давай оценку - одно решение лучшее
для решения : умение пользоватся языком С и его стандартной библиотекой другое

qulinxao ★★☆
()

и замени везде & на &&. В этом может быть трабл. Бо & - это битовая операция. А && - логическая.

точнее не везде, а там где она в if стоит

dikiy ★★☆☆☆
()
Ответ на: комментарий от qulinxao

Какой уж был :) Теперь поздно выбирать. Уже давно диплом получен и успешно положен на полочку.

delete83 ★★
()
Ответ на: комментарий от yurikoles

to10^100
1)
google:// :
.... в том, что люди могут говорить о говорении, и таким образом подвергать его сомнению. Далее из этого следует, что мы можем выдвигать сформулированные утверждения (и даже отрицательные утверждения) о том, что есть, и чего нет. Бейтсон отмечает, что подобные денотативные утверждения всегда действуют на «множестве уровней абстракции» (ibid). ...

2)
google:// :

http://iproc.ru/2011/06/why-i-still-program/
...суть ком­пью­тер­ных на­ук за­клю­ча­ет­ся в спо­соб­но­сти по­ни­мать мно­го уров­ней аб­страк­ции од­но­вре­мен­но.

qulinxao ★★☆
()

Переполнение буфера же.

fscanf(f,«%s %s %s»,d,p,s);

затирает содержимое переменной head, когда одно из слов больше 7, 3 или 3 символов соответственно.

kim-roader ★★
()
Ответ на: комментарий от kim-roader

А переполнение, судя по файлу, происходит каждый раз. Так что срабатывает твой код только на самой первой строчке, пока head ещё не важен.

kim-roader ★★
()
Ответ на: комментарий от yurikoles

Человек которому требуется обьяснение не понял и не понимает
(будем надеятся что когда либо поймёт буде такая необходимость)
Человек который понял не нуждается в обьяснении

ты прав , правила жизни Конвея напомниш?

qulinxao ★★☆
()
Ответ на: комментарий от ssvda

условие на прекращение+концевая рекурсия тут экстравагантная альтернатива циклу ибо входные данные гарантируют что озу хватит :)

qulinxao ★★☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.