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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> просле присваивания в памяти появляется ерунда 
:(
    Опции темы
CyberDemon
Дата 5.8.2008, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 83
Регистрация: 11.10.2003
Где: Нижний Новгород

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



У меня просто фокусы в таком коде:

Код

DWORD CMakeMess::IncodingToUnicode(char* cDataIn, char* cDataOut, DWORD iLen)
{
    DWORD i;
    char* cTemp;
    cTemp = new char[4];
    for(i = 0; i < iLen; i++)
    {
        memset(cTemp, 0, 4);
        sprintf(cTemp, "%4X", UnicodeTable(cDataIn[i]));
        if(cTemp[0] != ' ') cDataOut[i*4] = cTemp[0];
        else cDataOut[i*4] = '0';
        if(cTemp[1] != ' ') cDataOut[(i*4)+1] = cTemp[1];
        else cDataOut[(i*4)+1] = '0';
        if(cTemp[2] != ' ') cDataOut[(i*4)+2] = cTemp[2];
        else cDataOut[(i*4)+2] = '0';
        if(cTemp[3] != ' ') cDataOut[(i*4)+3] = cTemp[3];
        else cDataOut[(i*4)+3] = '0';
    }
    delete [] cTemp;


Код

DWORD CMakeMess::MakeMessage(char* cMessageOut, char* cMessageIn, DWORD iMessageLen,
                             DWORD dwCode)
{
    DWORD dwSize;
    switch(dwCode)
    {
    case UNICODE:
        dwSize = IncodingToUnicode(cMessageIn, cMessageOut, iMessageLen);



Код

DWORD CMakeMess::AddMessage(char* cData, char* cMessageIn, DWORD dwMessageLen,
                            DWORD dwCode, DWORD dwStartPos)
{
    char* cTemp;
    cTemp = new char[dwMessageLen+8];
    memset(cTemp, 0, dwMessageLen+8);
    DWORD dwSize = MakeMessage(cTemp, cMessageIn, dwMessageLen, dwCode);
    if(dwSize == 0){delete [] cTemp; return 0;}



В общем, все чудеса происходят в цикле функции IncodingToUnicode. Сначала все хорошо присваивается, потом, в цикле 3-4 на присваивании cDataOut[(i*4)+1] = cTemp[1] происходят чудеса. символ то присваивается, в вот в cDataOut, после символа в памяти возникает всякая белебердистика. Причем, эта белебирдистика не мешает дальнейшему прохождению цикла, и он выполнятся дальше. Просто откуда этот мусор берется?

Это сообщение отредактировал(а) CyberDemon - 5.8.2008, 14:53
PM MAIL ICQ   Вверх
bel_nikita
Дата 5.8.2008, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

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



Код
cTemp = new char[5];// не 4, а 5!

sprintf - работает с си-строкой, т.е. в конец добавляется "\0"


--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
CyberDemon
Дата 5.8.2008, 15:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 83
Регистрация: 11.10.2003
Где: Нижний Новгород

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



Цитата


 cTemp = new char[5];// не 4, а 5!

 sprintf - работает с си-строкой, т.е. в конец добавляется "\0" 




Пробовал, не помогает. При этом и так работает, правда до определенного момента :(
PM MAIL ICQ   Вверх
Torsten
Дата 5.8.2008, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата(CyberDemon @  5.8.2008,  14:03 Найти цитируемый пост)
В общем, все чудеса происходят в цикле функции IncodingToUnicode. Сначала все хорошо присваивается, потом, в цикле 3-4 на присваивании cDataOut[(i*4)+1] = cTemp[1] происходят чудеса. символ то присваивается, в вот в cDataOut, после символа в памяти возникает всякая белебердистика. Причем, эта белебирдистика не мешает дальнейшему прохождению цикла, и он выполнятся дальше. Просто откуда этот мусор берется?

Как ты его видишь ?
Через дебаггер ?
Не очень понятно, в чем проблема. Если ты присваивашь Си строке значение 0, это озночает конец для нее.
--------------------
We have no begining, we have no end. We are infinite.
PM MAIL   Вверх
Earnest
Дата 5.8.2008, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Мусор там изначально, после new байты никак не инициализируются. Просто отладчик показывает буфер как строку (т.е. до первого нуля). В какой-то момент ты этот 0 заменяешь, и строка становится длинней. Не хочешь на это смотреть - обнули буфер заранее. НО это не страшно. Другое дело, что в IncodingToUnicode нужно действительно 5 символов выделять, иначе возможны наезды на память, особенно в релизе. Кроме того, зачем такую ерунду как 5 символов выделять динамически? Выдели в стеке буфер символов в 10, на всякий случай...
И мне не совсем понятно, как ты выделяешь память для выходного сообщения: если ты генеришь шестнадцатеричное представление входной строки в Unicode, то длина должна быть len*4 + 1.
И еще, проще сразу заполнить выходной буфер нулями, потом копировать туда по 4 байта cTemp  с помощью memcpy, потом заменить все пробелы на '0'... а то монстр получился из ерундовой функции... 


--------------------
...
PM   Вверх
bel_nikita
Дата 5.8.2008, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

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



CyberDemon, 
ось какая?
unicode это же 16 бит, а у тебя 4 байта



--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
CyberDemon
Дата 5.8.2008, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 83
Регистрация: 11.10.2003
Где: Нижний Новгород

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



По порядку:

Цитата

Как ты его видишь ?
Через дебаггер ?
Не очень понятно, в чем проблема. Если ты присваивашь Си строке значение 0, это озночает конец для нее. 

 Естесвенно черз дебагер. Выполняем тело цикла. Первое присвоение cDataOut = "A\0\0\0\0", второе cDataOut = "A8\0\0\0", а после третьего, которое по идии не должно нули менять в конце cDataOut = "A8E>>>>?MMMM?>>>>". Вот почему это так?

Цитата

Мусор там изначально, после new байты никак не инициализируются. росто отладчик показывает буфер как строку (т.е. до первого нуля

Для этого там и стоит memset(cTemp, 0, 4);

Цитата

выделять динамически? Выдели в стеке буфер символов в 10, на всякий случай...

Просто эксперементировал почему так. Изначально было в стеке. Сейчас переведу обратно. На счет [10], взял на заметку. Поэксперементирую-расскажу. Кстати да, если выделять 4, то при выходи из функии, если переменная объявлена как в стеке, вываливается ошибка, что простанство вокруг переменной искажено.... Знаем... smile

Цитата

ось какая?
unicode это же 16 бит, а у тебя 4 байта


WinXP. Мне просто надo код из Unicode в char перевести. Уверен, что уже есть такая функция, но коль уже написал таблицу кодов, жаль работу губить...
PM MAIL ICQ   Вверх
vinter
Дата 5.8.2008, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


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

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



Цитата(CyberDemon @  5.8.2008,  18:23 Найти цитируемый пост)
сли выделять 4, то при выходи из функии, если переменная объявлена как в стеке, вываливается ошибка, что простанство вокруг переменной искажено.... Знаем... 

5 должно быть


--------------------
Мой блог
PM MAIL WWW   Вверх
Torsten
Дата 5.8.2008, 20:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



CyberDemon, 
Подобные вещи всегда лучше делать в отдельных тестовых проектах, а затем интегрировать в настоящий проект.
Советую тебе так сделать - навярника при создании тестового примера, все и найдешь сам.
Без тестового кода тут трудно разобратся, если ошибки, которые могут проевлятся гораздо раньше, чем видишь их последствия. У тебя может даже в функции EncodingToUnicode ошибка, а где-то в другом месте.
--------------------
We have no begining, we have no end. We are infinite.
PM MAIL   Вверх
CyberDemon
Дата 5.8.2008, 20:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 83
Регистрация: 11.10.2003
Где: Нижний Новгород

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



В общем так не до чего и не докопался. Сделал тупым, но надежным способом:

Код

    for(i = 0; i < iLen; i++)
    {
        memset(cTemp, 0, 10);
        sprintf(cTemp, "%4X", UnicodeTable(cDataIn[i]));
        if(cTemp[0] != ' ')
        {
            cDataOut[i*4] = cTemp[0];
            cDataOut[(i*4)+1] = NULL;
        }
        else cDataOut[i*4] = '0';
        if(cTemp[1] != ' ')
        {
            cDataOut[(i*4)+1] = cTemp[1];
            cDataOut[(i*4)+2] = NULL;
        }
        else cDataOut[(i*4)+1] = '0';
        if(cTemp[2] != ' ')
        {
            cDataOut[(i*4)+2] = cTemp[2];
            cDataOut[(i*4)+3] = NULL;
        }
        else cDataOut[(i*4)+2] = '0';
        if(cTemp[3] != ' ')
        {
            cDataOut[(i*4)+3] = cTemp[3];
            cDataOut[(i*4)+4] = NULL;
        }
        else cDataOut[(i*4)+3] = '0';
    }



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

Цитата

Подобные вещи всегда лучше делать в отдельных тестовых проектах, а затем интегрировать в настоящий проект.



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


P.S. По совету Earnest сделал char cTemp[10];. Т.е. увеличел иазмер и вернул в стек.

Это сообщение отредактировал(а) CyberDemon - 5.8.2008, 20:55
PM MAIL ICQ   Вверх
xvr
Дата 6.8.2008, 11:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(CyberDemon @ 5.8.2008,  14:03)
У меня просто фокусы в таком коде:

Код

DWORD CMakeMess::IncodingToUnicode(char* cDataIn, char* cDataOut, DWORD iLen)
{
    DWORD i;
    char* cTemp;
    cTemp = new char[4];
    for(i = 0; i < iLen; i++)
    {
        memset(cTemp, 0, 4);
        sprintf(cTemp, "%4X", UnicodeTable(cDataIn[i]));
        if(cTemp[0] != ' ') cDataOut[i*4] = cTemp[0];
        else cDataOut[i*4] = '0';
        if(cTemp[1] != ' ') cDataOut[(i*4)+1] = cTemp[1];
        else cDataOut[(i*4)+1] = '0';
        if(cTemp[2] != ' ') cDataOut[(i*4)+2] = cTemp[2];
        else cDataOut[(i*4)+2] = '0';
        if(cTemp[3] != ' ') cDataOut[(i*4)+3] = cTemp[3];
        else cDataOut[(i*4)+3] = '0';
    }
    delete [] cTemp;


Функция просто афигеть  smile Так не пробовал?

Код

DWORD CMakeMess::IncodingToUnicode(char* cDataIn, char* cDataOut, DWORD iLen)
{
    for(i = 0; i < iLen; i++)
    {
        sprintf(cDataOut+i*4, "%04X", UnicodeTable(cDataIn[i]));
    }
}


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


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Цитата(CyberDemon @  5.8.2008,  18:23 Найти цитируемый пост)
Для этого там и стоит memset(cTemp, 0, 4);

Шутник... мусор-то у тебя в выходном буфере, куда ты по символу складываешь...


--------------------
...
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.0668 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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