LINUX.ORG.RU

Господа, помогите!


0

0

Проблема такая: Есть клиентская программка на Си, она общается с сервером через сокеты. Формат вывода сервера и его размер всегда разные поэтому для приема всего этого динамически выделяется память каждый раз разная (на char*). Когда размер вывода 2-4 кб все работает ок, а когда килобайт 20 - при выполнении любой стд. функции ( например fprintf и т.п. ) Segmentation Fault ... :(

Уже перепробовал столько способов ... Пока спасло только чтение из полученной строки посимвольно и запись в файл посимвольно, через цикл, но это так тормозит прогу, что ужас ...

Буду благодарен за совет.

ЗЫ. Забыл сказать, используется на ОС freeBSD, так что не знаю, туда ли я попал ... Но прошу не посылать, т.к. по freeBSD я вообще ничего такого не нашел :(

anonymous

Re: Господа, помогите!

Как мне показал опыт, с этой ошибкой надо разбираться в сорцах. Может хотябы фрагментами кода дополнишь?

anonymous ()

Re: Господа, помогите!

Я делал так:

bool readWait(int sd, int len) {
fd_set set;
FD_ZERO(&set);
FD_SET(sd, &set);
timeval tv;
tv.tv_sec = len;
tv.tv_usec = 0;
if (select(sd + 1, &set, NULL, NULL, &tv) > 0)
return true;
return false;
}

bool writeWait(int sd, int len) {
fd_set set;
FD_ZERO(&set);
FD_SET(sd, &set);
timeval tv;
tv.tv_sec = len;
tv.tv_usec = 0;
if (select(sd + 1, NULL, &set, NULL, &tv) > 0)
return true;
return false;
}

bool writeSocket(int sd, char *buff, unsigned int len, int timeout) {
if (!writeWait(sd, timeout))
return 0;
unsigned int size = 0;
do {
if (writeWait(sd, 1)) {
int writen = send(sd, (void *)(buff + size), len - size, 0);
if (writen > 0)
size = size + writen; else
break;
} else
break;
} while(size < len);
return size == len;
}

bool readSocket(int sd, char *buff, unsigned int len, int timeout) {
if (!readWait(sd, timeout))
return 0;
unsigned int size = 0;
do {
if (readWait(sd, 1)) {

int readed = recv(sd, (void *)(buff + size), len - size, 0);
if (readed > 0)
size = size + readed; else
break;
} else
break;
} while(size < len);
return size == len;
}

А потом писал и читал из сокета используя эти функции.Надо сказать, что перед любым чтением и записью я знал размер данных. Так как протокол мой, то я себе таким образом облнгчил жизнь. Хотя можно было читать пока читается :))

Banshee ()

Re: Господа, помогите!

Segmentation fault обычно происходит при выходе за границы массива, так что посмотри в то место, где ты выделяешь память. Ещё может быть, что ошибка на самом деле произошла раньше. Так что, попробуй проверить все malloc'и (вручную или с помощью какой-нибудь программы типа ElectricFence).

justme ()

Re: Господа, помогите!

Вот моя фунция для чтения из сокета:

char *read_socket(void) {

char buff[512]; char first_line[512];

char* output; int output_point = 0;

int flag = 0; int inm = 0; int u = 0; int size = 1;

while(u<=size) { readline(popfd,buff,512);

if(inm==0) { sscanf(buff,"+OK %d ",&size); } else {

u += strlen(buff); };

if(!strcmp(first_line,buff)) break; if(strstr(buff,"+OK")!=NULL && inm!=0) break;

if(inm==0){ first_line = buff; output = (char*)malloc(sizeof(char)*size); } else { for(int ik=0; ik<strlen(buff); ik++) { *output++ = buff[ik]; output_point++; }

}

inm=1; }

output-=output_point;

return output;

}

Она работает всегда, т.е. никаких ошибок даже при получении полумега данных не сбоит. Странное происходит далее: Вот 2 способа записи полученных данных в файл:

1. char* output = read_socket();

for(int pp=0;pp<strlen(output);pp++) { fputc(output[pp],fp); }

2.

char* output = read_socket(); fprintf(fp,output);

Первый работает всегда, что говорит о том, что вся память аллокирована верно, второй на больших размерах массива output выдает Segmentation fault :(

anonymous ()

Re: Господа, помогите!

К последнему: Простите, перепутал. Segmentation fault вылетает не на fprintf, а на printf, на fprintf просто что-то странное: Программа пишет в файл всякий мусор, файл вырастает до нереальных размеров - 100 мб, когда ввод килобайт 20-30 ... И программу удается либо убить, либо по таймауту остановить ...

anonymous ()

Re: Господа, помогите!

А слабо fwrite использовать :))

Banshee ()

Re: Господа, помогите!

Ха! Тогда ясно - у тебя в output скорее всего появилось что-то вроде комбинации %s или %d, и fprintf начал радостно брать со стека параметры, которых там нет. В общем, либо используй fwrite, как сказал Banshee, либо fputs.Очередной пример ошибки, которая могла возникнуть только в программе на популярном языке C.

justme ()

Re: Господа, помогите!

Фигня у тебя. 1. Ты используешь first_line не проинициализировав Напиши хотябы в описании char first_line[512]="" 2. first_line=buff замени на strcpy(first_line,buff) 3. При копировании из buff в output поставь просто strncpy(output,buff,size) при этом не нужен output-=output_point а то у тебя нулевой символ не копируется, и кто гарантрует согласованость size и strlen(buff) Может еще чего незаметил, но пока все, тестируй, пиши.

anonymous ()

Re: Господа, помогите!

Ах да, еще. замени fprintf(fp,output) на fprintf(fp,"%s",output)

anonymous ()

Re: Господа, помогите!

Ой, немного ошибся в предпредыдущем послании в пункте 3. Цикл опустил из рассмотрения. После malloc-а добавим *output = '\0' а вместо strncpy будет strncat(output,buff,size-u) вроде как-то так. Ну дерзай, вдруг поможет.

anonymous ()

Re: Господа, помогите!

Господа! Спасибо! Ушел пробовать все варианты. Про %s - наиболее вероятно :(

Потом доложу о результатах ;)

Спасибо еще раз!

anonymous ()

Re: Господа, помогите!

Проверил, все работает!!!!! Спасибо всем!

Все-таки мир не без добрых людей :) !

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