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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблемы с изменением буфера и строк 
:(
    Опции темы
fire64
Дата 6.10.2009, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Я  для парсинга написал следующий код


Код

char *GetStringValue(char *string, char *word, char *firstbreak, char *endbreak)
{
    //Parser
    char *prename = strstr (string,word);

    char *name = (prename + strlen(word) );

    char *probel = ( strstr (name, firstbreak) + 1 );

    if(strstr (probel, endbreak))
    {
        char *newprobel = ( strstr (probel, endbreak) );
    
        int notprobellen = strlen(probel) - strlen(newprobel);

        char clear[2048];

        strncat (clear, probel, notprobellen);

        return clear;
    }
    else
    {
        return probel;
    }

    return NULL;
}


если я использую GetStringValue только один раз, то все нормально

а если 2 раза, то содержимое строк неправильное

Код

const char *Hubname = GetStringValue(Hubcfg, "$HubName:", "\x20", "\n");

const char *Topicname = GetStringValue(Hubcfg, "$Topic:", "\x20", "\n");


Hubname содержит не правильное значение, а точнее часть содержимого Topicname 

прошу помочь разобраться в проблеме

Это сообщение отредактировал(а) fire64 - 6.10.2009, 14:53
PM MAIL   Вверх
niXman
Дата 6.10.2009, 15:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Код

#include <string>
#include <algorithm>

/***************************************************************************/

std::string get_text(const std::string& str, const std::string& beg, const std::string& end) {
    std::string::const_iterator open = std::search(str.begin(), str.end(), beg.begin(), beg.end());
    std::string::const_iterator close= std::search(str.begin(), str.end(), end.begin(), end.end());
    
    if ( open == str.end() || close == str.end() ) {
        return std::string();
    }
    
    std::advance(open, beg.length());
    return std::string(open, close);
}

/***************************************************************************/

int main(int argc, const char** argv) {
    const std::string open_tag("<tag>");
    const std::string close_tag("</tag>");
    const std::string str("gkjeihgei<tag>needle text</tag>kjbsbv");
    
    std::string result = get_text(str, open_tag, close_tag);

    return 0;
}

/***************************************************************************/


Это сообщение отредактировал(а) niXman - 6.10.2009, 15:04
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
xvr
Дата 6.10.2009, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(fire64 @ 6.10.2009,  14:52)
Код

        char clear[2048];
        strncat (clear, probel, notprobellen);



Конкатенация строки с неинициализированным мусором. Используй просто strncpy

Цитата

        return clear;
Возврат указателя на локальную переменную - грубейшая, и очень частая ошибка  smile 

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


Шустрый
*


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

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



xvr, а что это изменит ?

всеравно первая строка будет содержать содержимое второй

Это сообщение отредактировал(а) fire64 - 6.10.2009, 16:59
PM MAIL   Вверх
niXman
Дата 6.10.2009, 17:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



передай в функцию еще один параметр, т.е. указатель на буфер куда будет помещаться результат.
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
fire64
Дата 6.10.2009, 17:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Проблема решена

xvr,  спасибо за помощь в избавлении от мусора

niXman спасибо за совет с указателем на буфер

п.с.

помог перевод char* в char []

кстати буду рад если кто объяснит почему char* некорректно работал
PM MAIL   Вверх
niXman
Дата 6.10.2009, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата(fire64 @  6.10.2009,  15:29 Найти цитируемый пост)
кстати буду рад если кто объяснит почему char* некорректно работал 

Потому что ты возвращал указатель на локальный массив. А запись типа char[] предполагает возвращать копию массива.

п.с.
но я бы так не сделал. лучше передать указатель на массив в функцию.
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
fire64
Дата 6.10.2009, 19:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



ок спасибо за информацию

возникла новая проблема

программа падает в дебаг билде в функции парсинга (смотрите первый пост) при использовании sprintf
Код

    else
    {
        sprintf(result, "%s", probel);
    }



Код

-        probel    0x0044cb96 "fire64|"    char *
            102 'f'    char
-        result    0x00441064 ""    char *
            0    char


Код

    firehub.exe!write_char()  Строка 1083 + 0x20 байт    C
    firehub.exe!write_string()  Строка 1221 + 0x23 байт    C
    firehub.exe!_output()  Строка 983 + 0x18 байт    C
    firehub.exe!sprintf()  Строка 104 + 0x11 байт    C
    firehub.exe!GetStringValue()  Строка 40 + 0x12 байт    C++
    firehub.exe!ValidateNick()  Строка 51 + 0x20 байт    C++
    firehub.exe!NetworkThread()  Строка 164 + 0x9 байт    C++
    firehub.exe!_threadstart()  Строка 173 + 0xd байт    C
    kernel32.dll!7c80b729()    
    [Указанные ниже фреймы могут быть неверны и (или) отсутствовать, символы для kernel32.dll не загружены]    



PM MAIL   Вверх
Леопольд
Дата 6.10.2009, 20:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(niXman @  6.10.2009,  15:02 Найти цитируемый пост)
Код

#include <string>
#include <algorithm>
/***************************************************************************/
std::string get_text(const std::string& str, const std::string& beg, const std::string& end) {
    std::string::const_iterator open = std::search(str.begin(), str.end(), beg.begin(), beg.end());
    std::string::const_iterator close= std::search(str.begin(), str.end(), end.begin(), end.end());
...



std::string get_text(const std::string& str, const std::string& beg, const std::string& end) {
    std::string::const_iterator open = std::search(str.begin(), str.end(), beg.begin(), beg.end());
    std::string::const_iterator close= std::search(open, str.end(), end.begin(), end.end());

Немного оптимизации не повредит. Но это не распарсишь... :)
"gkjeihgei<tag>not needed text</tag><tag>needle text</tag>kjbsbv"

Это сообщение отредактировал(а) Леопольд - 6.10.2009, 20:02


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
niXman
Дата 6.10.2009, 20:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата(fire64 @  6.10.2009,  17:48 Найти цитируемый пост)
программа падает в дебаг билде в функции парсинга

А в релизе?
Кто такой result ?

Добавлено через 10 минут и 35 секунд
Леопольд, Тоже верно smile 
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
fire64
Дата 6.10.2009, 20:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



niXman, вот код

Код

void GetStringValue(char *string, char *word, char *firstbreak, char *endbreak, char *result)
{
    //Parser
    char *prename = strstr (string,word);

    char *name = (prename + strlen(word) );

    char *probel = ( strstr (name, firstbreak) + 1 );

    char clear[2048];

    if(strstr (probel, endbreak))
    {
        char *newprobel = ( strstr (probel, endbreak) );
    
        int notprobellen = strlen(probel) - strlen(newprobel);

        strncpy (clear, probel, notprobellen - 1);

        sprintf(result, "%s", clear);
    }
    else
    {
        sprintf(result, "%s", probel);
    }
}


в релизе падает тоже, но в другом месте

Код

            else
            {
                char sendcommand[1024];

                GetStringValue(meseg, "$", "", "NOT FOUND", sendcommand);  //падает здесь

                printf ("UNKNOWN COMMAND $%s \n", sendcommand );

                continue;
            }



PM MAIL   Вверх
niXman
Дата 6.10.2009, 20:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Возможно, объем буфера мал. Или "probel" равен NULL
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
xvr
Дата 6.10.2009, 20:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Вот тут
Код

        strncpy (clear, probel, notprobellen - 1);
        sprintf(result, "%s", clear);
strncpy не копирует в clear терминирующий ноль, т.к. исходная строка длиннее, чем выходной буфер (размер буфера - 3й параметр). Последующий sprintf пытается печатать в result строку неизвестной длинны (точнее, он шарашит по памяти пока не найдет 0). Происходит запись за границы массива со всеми вытекающими  smile 
Кстати, конструкция 
Код

    if(strstr (probel, endbreak))
    {
        char *newprobel = ( strstr (probel, endbreak) );
    
        int notprobellen = strlen(probel) - strlen(newprobel);
        strncpy (clear, probel, notprobellen - 1);
        sprintf(result, "%s", clear);
    }
    else
    {
        sprintf(result, "%s", probel);
    }
мало того, что неправильная, она еще и неэффективная  smile 
Код

if (char* newprobel = strstr (probel, endbreak))
{
 int len=newprobel-probel-1;
 memcpy(result,probel,len)[len]=0;
}
else
{
 strcpy(result,probel);
}

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


Бывалый
*


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

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



Я вообще не понимаю, почему бы не воспользоваться моим примером кода.
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
zim22
Дата 6.10.2009, 21:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


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

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



Цитата(niXman @  6.10.2009,  21:01 Найти цитируемый пост)
Я вообще не понимаю, почему бы не воспользоваться моим примером кода.

у тебя код на С++. fire64 же привёл пример на Си.


--------------------
PM MAIL   Вверх
fire64
Дата 6.10.2009, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



xvr, теперь программа падает в strcpy(result,probel)

хотя в release в этом месте все в порядке

от замены моей конструкции на твою ничего не изменилось

Это сообщение отредактировал(а) fire64 - 6.10.2009, 22:21
PM MAIL   Вверх
niXman
Дата 6.10.2009, 22:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Где-то порча кучи. Пройдись дебагером.
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
fire64
Дата 6.10.2009, 23:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



есть подозрение что проблема связана с ClientIP

Код


struct clientnetinfo
{
    sockaddr_in client_addr;
    SOCKET        client_socket; 
    char        clientuserdata[1024];
}; 

clientnetinfo *ClientIP;

int main(int argc, char *argv[])
{

ClientIP = new clientnetinfo[1024]; 

send(ClientIP[userid].client_socket,WELKOM,strlen(WELKOM),0);

_beginthread( NetworkThread, 0, (void*)userid );

}


Плюс я не уверен что безопасно использовать ClientIP  из другого потока

void NetworkThread(void *userid) 
{
        int uerid = (int)userid;

        nNumRead = recv(ClientIP[uerid].client_socket, msg, MAX_MSG, 0);

}



PM MAIL   Вверх
niXman
Дата 7.10.2009, 01:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата(fire64 @  6.10.2009,  21:00 Найти цитируемый пост)
Плюс я не уверен что безопасно использовать ClientIP  из другого потока

Если пока работают потоки, данные в ClientIP не изменяются, то безопасно.

Это сообщение отредактировал(а) niXman - 7.10.2009, 01:18
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
fire64
Дата 7.10.2009, 01:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



хм вообще-то изменяются

Код

у меня в void NetworkThread(void *userid) 


используется код

Код

strcpy(ClientIP[uerid].clientuserdata, userdata );


для каждого пользователя создается свой поток

в int main(int argc, char *argv[])

используется код

Код

    while(1) 
    {
        userid ++;

        fromlen=sizeof(ClientIP[userid].client_addr);

        ClientIP[userid].client_socket=accept(name_sock, (struct sockaddr*)&ClientIP[userid].client_addr, &fromlen );

        send(ClientIP[userid].client_socket,WELKOM,strlen(WELKOM),0);

        userscount = userid;

        _beginthread( NetworkThread, 0, (void*)userid );

     }


Это сообщение отредактировал(а) fire64 - 7.10.2009, 01:33
PM MAIL   Вверх
niXman
Дата 7.10.2009, 01:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Займись синхронизацией.
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
fire64
Дата 7.10.2009, 01:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



niXman, думаешь из-за этого  происходит порча кучи ?



PM MAIL   Вверх
niXman
Дата 7.10.2009, 02:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



fire64, Не уверен.
Поразмышляю вслух. Допустим, в то время, как один из потоков, читает из своего элелента массива, данные/строку(или что это?), другой поток, в это же время, пишет в нее, то поток(читающий), не дочитав прежние данные из строки, начинает читать новые. Не видя кода целиком, сказать точно сложно. Но, использовать многопоточный код, когда один из потоков является модификатором, без синхронизации опасно.

Добавлено через 6 минут и 4 секунды
Покажи весь код, если не секрет smile 

Это сообщение отредактировал(а) niXman - 7.10.2009, 02:03
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
fire64
Дата 7.10.2009, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



ок

держи исходники и скомпиленый DC хаб

на данный момент поддерживается только чат

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  firedc.rar 34,85 Kb
PM MAIL   Вверх
xvr
Дата 7.10.2009, 11:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(fire64 @ 6.10.2009,  22:19)
xvr, теперь программа падает в strcpy(result,probel)

probel случайно в этом месте не равен NULL?
И вообще результаты всех поисков (strstr, strchr и пр) рекомендуется проверять на NULL. А если то, в чем ищут приходит извне, то НАСТОЯТЕЛЬНО рекомендуется  smile 
PM MAIL   Вверх
fire64
Дата 7.10.2009, 11:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



хм теперь стало вылетать на 

fread (MotdText,1, len, motd);

хотя я тот код и не трогал, очень странные вылеты по всему коду

xvr, я уверен что там нет нулей, да и дебагер показщывает что там "Fire64|"


Это сообщение отредактировал(а) fire64 - 7.10.2009, 11:56
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.1190 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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