Анекдот для настоящего программисти
Проблемы с памятью
Люди помогите плиз! Написал прогу, которая распознает некоторые протоколы канального уровня. Исходные данные - некоторое количество файлов с перехваченным трафиком. Все вроде работает. Однако при тестах на большом количестве данных (3-4 тысячи файлов, общий размер порядка гига) обнаруживается неясная фигня: процесс жрет память по возрастающей, доходит до 120-150 метров. Однако, если прога в режиме дебага доходит до брейкпойнта, объем памяти при остановке сразу падает до приемлемого уровня мегов 10-20. Прога консольная, указателей почти нет, вроде бы все, что создается в одной итерации цикла, там же и уничтожается, так что ее прожорливость заставляет задуматься. Привожу исходник(win2000, MSVC++6.0):
code:
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <direct.h>
#include <stdlib.h>
#include <iostream.h>
#include <math.h>
#include <ctime>
typedef unsigned char uchar;
typedef unsigned short int u16;
u16 fcstab[256] = {
0x0000,.../*здесь значения для вычисления CRC*/..., 0x1EF0
};
u16 CheckCRC(uchar *buf, u16 len)
{
u16 fcs = 0x0000;
if(len !=
{
for(int i=8; i<len; i++)
fcs = (fcs<<^fcstab[(fcs>>^buf[i]];
}
for(int i=5; i<8; i++)
fcs = (fcs<<^fcstab[(fcs>>^buf[i]];
return (fcs);
}
//------------------------------------------------
int pppident(char *dir, char *filename)
{
char substr[2];
int count;
int *interval;
long int prevpoz;
interval = new int [100000];
strcpy(substr, "~~");
count=0;
FILE *fp, *fout;
char pppdir[1000];
char str[2];
strcpy(str, " ");
strcpy(pppdir, dir);
strcat(pppdir, "\PPP");
if ((fp=fopen(filename, "rb"))==NULL) {
cout << "Cannot open file!ppp" << endl;
delete [] interval;
return 0; }
long int flen=0;
int ch;
interval[0]=0;
prevpoz=0;
fread(str, 2, 1, fp);
while (!feof(fp)) {
if (strcmp(str, substr)==0) {
count++;
interval[count]=flen-prevpoz;
prevpoz=ftell(fp);
fread(str, 2, 1, fp);
flen=ftell(fp);
if (count==100000)
{cout << "Massive overflow" << endl;
float t=(float)count/(float)flen*100;
float tmin=1;
tmin=tmin/10;
if (t>=tmin) {cout << "File" << filename << "maybe contains PPP packets" << endl;}
getch();
delete [] interval;
fclose(fp);
return 0;}
}
else {
str[0]=str[1];
str[1]=fgetc(fp);
flen=ftell(fp); }
}
float niu;
niu=(float)count/(float)flen*100;
float niuet=1;
niuet=niuet/30;
if (niu < niuet)
{
delete [] interval;
fclose(fp);
return 0;
}
float mo=0;
for (int i=1; i<=count; i++)
{
mo=mo+(float)interval[i];
}
mo=mo/(float)count;
float disp=0;
float tmp=0;
for (i=1; i<=count; i++)
{ tmp=(float)interval[i]-mo;
tmp=pow(tmp, 2);
disp=disp+tmp;
}
disp=disp/(float)(count-1);
niuet=1;
niuet=niuet/10;
float momin=10;
float momax=1000;
if (!((niu>=niuet)&&(mo>=momin)&&(mo<=momax)))
{delete [] interval;
fclose(fp);
return 0;}
fseek(fp, 0L, SEEK_SET);
chdir(pppdir);
if ((fout=fopen(filename, "wb"))==NULL) {
cout << "Cannot open file!ppp2" << endl;
delete [] interval;
return 0; }
ch=fgetc(fp);
while(!feof(fp))
{
fputc(ch, fout);
ch=fgetc(fp);
}
chdir(dir);
delete [] interval;
fclose(fp);
fclose(fout);
return 1;
}
int blastident(char *dir, char *filename)
{
int count=0;
int *interval;
long int prevpoz;
interval = new int [100000];
FILE *fp, *fout;
char blastdir[1000];
strcpy(blastdir, dir);
strcat(blastdir, "\Blast");
if ((fp=fopen(filename, "rb"))==NULL) {
cout << "Cannot open file!blast" << endl;
delete [] interval;
return 0; }
char blstr[26];
int ch;
fread(blstr, 25, 1, fp);
blstr[25]=' ';
if (strcmp(blstr, ";starting BLAST protocol.")==0)
{
fseek(fp, 0L, SEEK_SET);
chdir(blastdir);
if ((fout=fopen(filename, "wb"))==NULL) {
cout << "Cannot open file!blast2" << endl;
delete [] interval;
fclose(fp);
return 0; }
ch=fgetc(fp);
while(!feof(fp))
{
fputc(ch, fout);
ch=fgetc(fp);
}
chdir(dir);
fclose(fp);
fclose(fout);
return 1;
}
long int flen=0;
interval[0]=0;
prevpoz=0;
uchar buf[4];
fseek(fp, 0L, SEEK_SET);
fread(buf, 4, 1, fp);
while (!feof(fp)) {
if ((buf[0]==0x2E)&&(buf[1]==0x0D))
{ if ((buf[2]==0x3B)||(buf[2]==0x2C))
if ((buf[3]==0x30)||(buf[3]==0x31))
{
count++;
interval[count]=flen-prevpoz;
prevpoz=ftell(fp);
fread(buf, 4, 1, fp);
flen=ftell(fp);
continue;
}
}
buf[0]=buf[1];
buf[1]=buf[2];
buf[2]=buf[3];
buf[3]=fgetc(fp);
flen=ftell(fp);
}
float niu;
niu=(float)count/(float)flen*100;
float mo=0;
for (int i=1; i<=count; i++)
{ mo=mo+(float)interval[i];
}
mo=mo/(float)count;
float disp=0;
float tmp=0;
for (i=1; i<=count; i++)
{ tmp=(float)interval[i]-mo;
tmp=pow(tmp, 2);
disp=disp+tmp;
}
disp=disp/(float)(count-1);
float niuet=5;
niuet=niuet/10;
float momin=8;
float momax=150;
if (!((niu>=niuet)&&(mo>=momin)&&(mo<=momax)))
{delete [] interval;
fclose(fp);
return 0;}
fseek(fp, 0L, SEEK_SET);
chdir(blastdir);
if ((fout=fopen(filename, "wb"))==NULL) {
cout << "Cannot open file!blast3" << endl;
delete [] interval;
fclose(fp);
return 0; }
ch=fgetc(fp);
while(!feof(fp))
{
fputc(ch, fout);
ch=fgetc(fp);
}
chdir(dir);
fclose(fp);
fclose(fout);
return 1;
}
int gwdident(char *dir, char *filename)
{
FILE *fp, *fout;
uchar temp_buf[8],
*buffer,
ch,
weight,
typepac[18] = {0x01, 0x11, 0x13, 0x14, 0x15, 0x16,
0x20, 0x23, 0x25, 0x53, 0x54, 0x65,
0x87, 0x91, 0x94, 0x95, 0x96};
u16 i, count=0;
u16 pacLength,
getCRC;
fpos_t begin_packet;
bool CRCok;
int rezult;
if ((fp=fopen(filename, "rb"))==NULL) {
cout << "Cannot open file!gwd" << endl;
return 0; }
char gwddir[1000];
strcpy(gwddir, dir);
strcat(gwddir, "\Gateway");
while(!feof(fp))
{
CRCok = false;
fgetpos(fp, &begin_packet);
ch = fgetc(fp);
if(ch == 0x02)
{
for(i=0; i<7; i++)
{
temp_buf[i] = fgetc(fp);
}
getCRC = 0;
getCRC = temp_buf[3];
getCRC <<=8;
getCRC |= temp_buf[2];
pacLength = 0;
pacLength = temp_buf[5];
pacLength <<=8;
pacLength |= temp_buf[4];
fsetpos(fp, &begin_packet);
pacLength += 7;
if(!buffer)
delete [] buffer;
buffer = NULL;
buffer = new uchar[pacLength+1];
if(!buffer)
{
cout << "Insuffient memory for a packet buffer";
continue;
}
for(i=0; i<pacLength; i++)
{
if(feof(fp))
{
begin_packet++;
fsetpos(fp, &begin_packet);
break;
}
buffer[i] = fgetc(fp);
}
weight = 0;
for(i=0; i<17; i++)
{
if(buffer[7] == typepac[i])
{
weight += 10;
break;
}
}
ch = fgetc(fp);
if(feof(fp))
ch = 0x02;
if(ch == 0x02)
weight += 40;
if(getCRC == CheckCRC(buffer, pacLength))
{
CRCok = true;
weight += 50;
}
if(weight>=40) count++;
if (count==2) break;
}
}
if (count>1)
{
fseek(fp, 0L, SEEK_SET);
chdir(gwddir);
if ((fout=fopen(filename, "wb"))==NULL) {
cout << "Cannot open file!gwd2" << endl;
return 0; }
ch=fgetc(fp);
while(!feof(fp))
{
fputc(ch, fout);
ch=fgetc(fp);
}
chdir(dir);
fclose(fp);
fclose(fout);
delete [] buffer;
buffer=NULL;
rezult=1;
}
return rezult;
}
int main()
{
struct _finddata_t p;
char curdir[1000];
char infile[260];
int rez=0;
long int done=0;
long int hFile;
clock_t start, finish;
start=clock();
if (getcwd(curdir, sizeof(curdir))==NULL)
perror("?????? getcwd");
mkdir("PPP");
mkdir("Blast");
mkdir("Gateway");
hFile=_findfirst("*.*", &p);
FILE *ftlp=NULL;
ftlp=fopen("1.log", "w");
while (!done)
{
if (!(p.attrib&_A_SUBDIR))
{
strcpy(infile, p.name);
rez=pppident(curdir, infile);
if (!rez) rez=blastident(curdir, infile);
if (!rez) rez=gwdident(curdir, infile);
cout << infile << endl;
fprintf(ftlp, infile);
fprintf(ftlp, "n");
}
done = _findnext(hFile, &p);
}
finish=clock();
start=finish-start;
start=start/CLOCKS_PER_SEC;
cout << start << endl;
fprintf(ftlp, "%d", start);
fprintf(ftlp, "n");
fclose(ftlp);
_findclose(hFile);
return 0;
}
Кроме того, когда память забивается примерно на 150 мегов (всего на машине 256) fopen() на всех последующих файлах начинает возвращать 0, однако ошибки не видно, так как все значения переменных в этот момент допустимые. (
Подскажите, плз, от чего така бяка может быть?
(((