Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> проблема при работе с памятью 
:(
    Опции темы
alexanderd
Дата 3.11.2011, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 3.11.2011

Репутация: нет
Всего: нет



Здравствуйте.
Возникла трабла непонятного происхождения при работе с памятью.
Есть следующий код:
Код

while (...){
        char* buff = dataBuffer->ptr + dataBuffer->size;

        if ((rcv_size = recv(recvSocket, buff, pack_lng, 0)) > 0){
            dataBuffer->size += rcv_size;
        }
}


dataBuffer - структура, которая описывает буфер определенного размера, куда сваливаются все данные, полученные с сокета,
buff- указатель на хвост буфера
В цикле получаем данные с сокета и дописываем их в конец буфера.
Данные нормально приняты и записаны в буфер.
После получения данные из буфера пишутся в файл.

Возникла необходимость выкидывать первые четыре байта из каждой порции данных,
полученной с сокета. Первое и пока единственное, что пришло на ум:
Код

char tmp_buff[1500];
while (...){
    char* buff = dataBuffer->ptr + dataBuffer->size;

    if ((rcv_size = recv(recvSocket, tmp_buff, pack_lng, 0)) > 0){
        memmove(buff,&tmp_buff[4],rcv_size-4);
        dataBuffer->size += rcv_size-4;
    }
        
}


Создаем временный буфер tmp_buff и записываем данные в него,
затем перемещаем(или копируем) данные из него в основной буфер со смещением в четыре байта.

На передающей стороне происходит следующее:
с диска считывается файл по куску в 1400 байт. К этому куску добавляется
заголовок в 4 байта и вот эти вот 1404 байта я получаю у себя. Потом я отбрасываю
четырехбайтовый заголовок, а блок, записываю в буфер. И продолжаю писать
в буфер до тех пор, пока передающая сторона полностью не отправит мне файл.
После этого соединение разрывается. А из буфера данные перекидываются в файл.

В итоге исходный файл и файл, записанный мной, отличаются по размерам, не более чем
на килобайт при размере самого файла в несколько метров. И разница в размерах кратна
четырем.

При этом, если передающая сторона не добавляет заголовок, и я убираю код,
по обработке заголовков, то никаких проблем не возникает...

Не знаю даже в какую сторону копать... (((
Буду признателен всем за помощь

PS. В кач-ве среды разработки используется MSVS2008, компилятор родной для этой среды, никаких опции не менял



PM MAIL   Вверх
bsa
Дата 3.11.2011, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



во-первых, использование memmove не оптимально. Так как memmove делает 2 операции копирования + одну выделения и одну освобождения памяти. Лучше используй memcpy, если исходный буфер и буфер назначения не пересекаются.
во-вторых, я бы делал через считывание первых 4-х байт во временный буфер, а затем уже остальных данных в основной буфер.

Но в целов в твоем коде ошибок не видно.

Ты точно уверен, что проблема не в отправляющей стороне? Точно приходит по 1404 байт?
PM   Вверх
volatile
Дата 4.11.2011, 00:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



 smile 
Цитата(bsa @  3.11.2011,  16:12 Найти цитируемый пост)
Так как memmove делает 2 операции копирования + одну выделения и одну освобождения памяти


bsa, я не смотрел исходники memmove, но думаю что задачу копирования пересекающихся областей можно сделать без 2 операций копирования и выделения.
пример (упрощенный)
Код

void memmove (char* dst, char* src, ulong size)
{
   if (dst < src)
      while (size--)
         *dst++ = *src++;
   else
   {
      dst += size - 1;
      src += size - 1;
      while (size--)
         *dst-- = *src--;
   }
}
(написал на коленке, работоспособность не проверял)

Цитата(alexanderd @  3.11.2011,  15:35 Найти цитируемый пост)
На передающей стороне происходит следующее:
с диска считывается файл по куску в 1400 байт. К этому куску добавляется
заголовок в 4 байта и вот эти вот 1404 байта я получаю у себя

alexanderd, так как код отправляющей стороны вы не привели, приходиться гадать на кофейной гуще. 
Очень похоже, что идет выравнивание структуры на 8 байт. В итоге получается не 1404, и 1408 байт.
Нужен код отправляющей стороны.

Это сообщение отредактировал(а) volatile - 4.11.2011, 00:35
PM MAIL   Вверх
math64
Дата 4.11.2011, 13:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



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

memmove() работает примерно так, как описал volatile - основной цикл - это команда rep movs с установленным предварительно флагом напрвления копирования; но в данном случае можно использовать memcpy(), так как буферы не пересекаются (не будет проверки на пересечение)

PM   Вверх
bsa
Дата 6.11.2011, 21:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(volatile @  4.11.2011,  01:18 Найти цитируемый пост)
bsa, я не смотрел исходники memmove, но думаю что задачу копирования пересекающихся областей можно сделать без 2 операций копирования и выделения.
пример (упрощенный)
Цитата(math64 @  4.11.2011,  14:24 Найти цитируемый пост)
memmove() работает примерно так, как описал volatile - основной цикл - это команда rep movs с установленным предварительно флагом напрвления копирования;

Недавно тут обсуждали реализацию memmove от MS. Так там именно описанная мной реализация и была. Естественно, что с точки зрения логики делать нужно было так.
PM   Вверх
volatile
Дата 7.11.2011, 00:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(bsa @  6.11.2011,  21:33 Найти цитируемый пост)
Недавно тут обсуждали реализацию memmove от MS. Так там именно описанная мной реализация и была. 

bsa, M$ конечно много всякой фигни поднаделало, и лишний раз кинуть камень в их огород считается хорошим тоном. Но давайте будем объективны. У них получился очень недурственный компилер С++ в плане оптимизации. Не в обиду поклонникам других систем!
MS конечно-же отстает в добавлении новых фич, как то новые стандарты, и т.д. это да! Но что у них не отнять, это очень и очень неплохая оптимизация! я просто не верю что они могли прошляпить такую вещь.

Добавлено через 9 минут и 39 секунд
Вот заглянул в crt 2008 студии
Исходник общей ( не оптимизированной ) memmove.c

Код

/***
*memmove.c - contains memmove routine
*
*       Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
*       memmove() copies a source memory buffer to a destination buffer.
*       Overlapping buffers are treated specially, to avoid propogation.
*
*******************************************************************************/

#include <cruntime.h>
#include <string.h>

/***
*memmove - Copy source buffer to destination buffer
*
*Purpose:
*       memmove() copies a source memory buffer to a destination memory buffer.
*       This routine recognize overlapping buffers to avoid propogation.
*       For cases where propogation is not a problem, memcpy() can be used.
*
*Entry:
*       void *dst = pointer to destination buffer
*       const void *src = pointer to source buffer
*       size_t count = number of bytes to copy
*
*Exit:
*       Returns a pointer to the destination buffer
*
*Exceptions:
*******************************************************************************/

void * __cdecl memmove (
        void * dst,
        const void * src,
        size_t count
        )
{
        void * ret = dst;

#if defined (_M_IA64) || defined (_M_AMD64)

        {


        __declspec(dllimport)


        void RtlMoveMemory( void *, const void *, size_t count );

        RtlMoveMemory( dst, src, count );

        }

#else  /* defined (_M_IA64) || defined (_M_AMD64) */
        if (dst <= src || (char *)dst >= ((char *)src + count)) {
                /*
                 * Non-Overlapping Buffers
                 * copy from lower addresses to higher addresses
                 */
                while (count--) {
                        *(char *)dst = *(char *)src;
                        dst = (char *)dst + 1;
                        src = (char *)src + 1;
                }
        }
        else {
                /*
                 * Overlapping Buffers
                 * copy from higher addresses to lower addresses
                 */
                dst = (char *)dst + count - 1;
                src = (char *)src + count - 1;

                while (count--) {
                        *(char *)dst = *(char *)src;
                        dst = (char *)dst - 1;
                        src = (char *)src - 1;
                }
        }
#endif  /* defined (_M_IA64) || defined (_M_AMD64) */

        return(ret);
}


Добавлено через 13 минут и 32 секунды
Вот здесь memmove под ARM процессоры (асм).

PM MAIL   Вверх
bsa
Дата 7.11.2011, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(volatile @  7.11.2011,  01:17 Найти цитируемый пост)
У них получился очень недурственный компилер С++ в плане оптимизации. Не в обиду поклонникам других систем!
Я ни слова не сказал о компиляторе. Ничего не имею против него.

Цитата(volatile @  7.11.2011,  01:17 Найти цитируемый пост)
Вот заглянул в crt 2008 студии
По-моему, там речь шла о 6-й. Но сильно настаивать не буду, так как не смог найти обсуждение.

PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.3611 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.