Форум программистов, компьютерный форум CyberForum.ru

Проблемы при работе с динамическим распределением памяти - C++

Восстановить пароль Регистрация
 
mutari
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
26.07.2011, 19:38     Проблемы при работе с динамическим распределением памяти #1
Здравствуйте! Возникла проблема при использовании динамической распределении памяти.
Вот код:
C++
1
2
3
4
5
6
7
8
9
10
char* zero;
char buf[64];
memset(buf_t,0,16);
temp = strlen(buf_t) ;
int len = 15-temp;
zero = new char [len];
memset(zero,0,sizeof(zero));
for( int i = 0; i <= len; i++)
    *(zero+i) = '0';
strcat(zero,buf_t);
Это отрывок программы. В buf_t содержится двоичное число, максимально состоящее из 16 разрядов. Суть функции в том, чтобы посмотреть сколько разрядов числа в buf_t и дописать с начала нулей, добив до 16 разрядов. Но вот после цикла в массиве zero содержится примерно следующее - "000000000000«««««««««««««««юоюою". Причём кол-во нулей сначала меня устраивает. Меня не устраивает то, что записано после них. Почему вообще столько ячеек в массиве, если в данном примере переменная temp = 4, а след. длина len = 11?


И ещё вопрос сюда же - в конце функции написал delete []zero; . Когда доходит до этой строчки выводит ошибку
ОС Windows инициировала точку останова в Test_c.exe.

Это может быть вызвано повреждением кучи и указывает на ошибку в Test_c.exe или в одной из загруженных им DLL.
Что я делаю не так? Заранее спасибо!
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alexcoder
1438 / 652 / 86
Регистрация: 03.06.2009
Сообщений: 3,286
Завершенные тесты: 1
26.07.2011, 20:57     Проблемы при работе с динамическим распределением памяти #2
Не совсем понятно что нужно, может так лучше?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
char* zero;
int temp;
char buf[64],buf_t[16];
memset(buf_t,0,16);
temp = strlen(buf_t) ;
int len = 15-temp;
zero = new char [len+1];//Добавить завершающий нулевой сивол
memset(zero,0,len+1);
for( int i = 0; i <= len; i++)
        *(zero+i) = '0';
strcat(zero,buf_t);
cout << zero;
delete zero;
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
26.07.2011, 21:18     Проблемы при работе с динамическим распределением памяти #3
Цитата Сообщение от mutari Посмотреть сообщение
Что я делаю не так?
видимо, полагаете, что sizeof(zero) даёт размер выделенного блока памяти. Увы, это размер указателя (обычно 4 или 8 байт). Переносимых способов определить размер динамически выделенного блока нет. Размер надо запоминать самостоятельно (что можно увидеть у alexcoder)
mutari
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
26.07.2011, 21:26  [ТС]     Проблемы при работе с динамическим распределением памяти #4
Второй вопрос отпал - спасибо! Помогло, когда убрал квадратные скобки.

Но первый остаётся открытым. Я, конечно, не досмотрел, когда писал сообщение - спутал названия переменных. Должно быть так:
C++
1
2
3
4
5
6
7
8
9
10
char* zero;
char buf_t[64];
memset(buf_t,0,16);
int temp = strlen(buf_t) ;
int len = 15-temp;
zero = new char [len];
memset(zero,0,sizeof(zero));
for( int i = 0; i <= len; i++)
        *(zero+i) = '0';
strcat(zero,buf_t);
Добавление ячейки для завершающего символа не помогло.
Смена sizeof(zero) на len+1 тоже.

Цитата Сообщение от alexcoder Посмотреть сообщение
Не совсем понятно что нужно, может так лучше?
Нужно сделать так, чтобы массив zero размером len заполнился len(таким количеством) нулями. И больше ничего, потому что строки нужно конкатенировать. А в итоге получается, что zero заполняется в случае len = 11 вот этим "000000000000«««««««««««««««юоюою". Количество нулей в норме. А вот "«««««««««««««««юоюою" мешает - при конкатенации с buf_t получается ерунда вместо 16-разрядного числа.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
26.07.2011, 21:49     Проблемы при работе с динамическим распределением памяти #5
C
1
2
3
4
5
6
char* zero;
int len = 15-temp;
zero = new char [len+1];
memset(zero,'0',len);
zero[len] = '\0';
strcat(zero,buf_t);
Добавлено через 17 минут
Цитата Сообщение от mutari Посмотреть сообщение
Второй вопрос отпал - спасибо! Помогло, когда убрал квадратные скобки.
Как раз с квадратными скобками правильно, а без них — нет.
mutari
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
26.07.2011, 22:16  [ТС]     Проблемы при работе с динамическим распределением памяти #6
Спасибо, это помогло - zero[len] = '\0';
Хотя я уже это добавлял, но видимо, надо было до цикла вставить.

Но почему-то вернулась проблема с delete [] zero; - выдаёт ту же ошибку. Почему может такое происходить?
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
26.07.2011, 22:17     Проблемы при работе с динамическим распределением памяти #7
Показывай, что получилось.
mutari
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
26.07.2011, 22:30  [ТС]     Проблемы при работе с динамическим распределением памяти #8
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void tau(char x1[64])
{
        char* zero;
        char    buf_t[64];
        memset(buf_t,0,16);
    int int_x1_10 = 0;
        int v=1;
    for(int num=15; num>=0; num--)
    {
        if(x1[num]=='1')
            int_x1_10+=v;
        v*=2 ;
    }
    int_x1_10++;
    itoa(int_x1_10,buf_t,2);
        
    int temp = strlen(buf_t) ;
    int len = 15-temp;
    zero = new char [len+1];
    memset(zero,0,len + 1);
    zero[len+1] = '\0';
    int i = 0;
    for( i = 0;i<=len; i++)
        *(zero+i) = '0';
    strcat(zero,buf_t);
    delete []zero;
}
Вот полностью код моей функции, с убранными выводами и вызовами других функций.
Ошибку выдаёт такую:
ОС Windows инициировала точку останова в Test_c.exe.

Это может быть вызвано повреждением кучи и указывает на ошибку в Test_c.exe или в одной из загруженных им DLL.

Возможной причиной так же может быть нажатие пользователем клавиши F12, когда фокус принадлежит Test_c.exe

Выведенное на экран окно содержит дополнительные данные для диагностики ошибки
В окне кнопки "Прервать", "Продолжить" и "Отмена"(неактивная).

Причём, как я только что заметил - Если два раза нажать "Продолжить", то программа выполняется до конца с правильным результатом.
Когда закомментировал строчку delete []zero; - выполнилась без ошибок.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
26.07.2011, 22:32     Проблемы при работе с динамическим распределением памяти #9
C++
1
2
zero = new char [len+1];
zero[len+1] = '\0';
Это выход за границу массива. Для буфера длиной len+1 последний допустимый индекс [len]
mutari
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
26.07.2011, 22:42  [ТС]     Проблемы при работе с динамическим распределением памяти #10
Когда я переписал zero[len] = '\0'; , вернулась проблема с белибердой в zero.
Не могли бы вы подсказать, как мне переписать этот код:
C++
1
2
3
4
5
6
7
8
int temp = strlen(buf_t) ;
        int len = 15-temp;
        zero = new char [len+1];
        memset(zero,0,len + 1);
        zero[len+1] = '\0';
        int i = 0;
        for( i = 0;i<=len; i++)
                *(zero+i) = '0';
чтобы массив zero заполнялся len+1 нулями, и соответственно был размером len+1, то есть от [0] до [len]
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
26.07.2011, 22:46     Проблемы при работе с динамическим распределением памяти #11
Я уже показывал. Но ещё раз, с уточнениями
C++
1
2
3
4
5
int temp = strlen(buf_t);
int len = 16-temp;
zero = new char [len+1];
memset(zero,'0',len);
zero[len] = '\0';
Просто вставте мой фрагмент вместо своего без исправлений. Цикл не нужен. Сразу после этого фрагмента strcat()

Добавлено через 50 секунд
Да, я увеличил len на 1.
mutari
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
26.07.2011, 23:10  [ТС]     Проблемы при работе с динамическим распределением памяти #12
А, я сначала недопонял просто. Да, этот вариант без цикла тоже работает, но на delete всё-равно ругается
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
26.07.2011, 23:15     Проблемы при работе с динамическим распределением памяти #13
Если вставлено без изменений, то проблема где-то в другом месте. Она может быть даже не в этой функции.
alexcoder
1438 / 652 / 86
Регистрация: 03.06.2009
Сообщений: 3,286
Завершенные тесты: 1
26.07.2011, 23:19     Проблемы при работе с динамическим распределением памяти #14
Я посмотрел функция, и насколько понял на входе двоичное число в виде массива, младшие значения по младшим адресам , а функция должна вывести младшие 16 разрядов числа.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void tau(char x1[64])
{
        char* zero;
        char    buf_t[64];
        memset(buf_t,0,16);
        int int_x1_10 = 0;
        int v=1;
        for(int num=15; num>=0; num--)
        {
                if(x1[num]=='1')
                        int_x1_10+=v;
                v*=2 ;
        }
        int_x1_10++;
        itoa(int_x1_10,buf_t,2);
                
        int temp = strlen(buf_t) ;
        int len = 15-temp;
        zero = new char [len+1];
        memset(zero,0,len + 1);
        zero[len+1] = '\0';
        int i = 0;
        for( i = 0;i<=len; i++)
                *(zero+i) = '0';
        strcat(zero,buf_t);
        delete []zero;
}
Может проще перевернуть число и все, например так:
C++
1
2
3
4
5
    char x1[64]="1010110000000000000000000000000000000000";
    char out[17]={0};
    for(int i=0;i<16;i++)
        out[15-i]=x1[i];
    cout << out;
З.Ы. Совсем запутался, если входной массив 64 символа, то почему он преобразовывается в целое с 15 индекса, не с 63?
mutari
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
27.07.2011, 00:49  [ТС]     Проблемы при работе с динамическим распределением памяти #15
Нет, суть функции в другом. В общем это часть dll библиотеки для работы с dhcp сервером, он должен выдавать ip в виде 172.18.x.x, где x.x увеличивающийся на один с каждым запросом адрес - в двоичном виде соответственно 16 бит (ip адрес = 32 бита).
Данная функция tau как раз увеличивает ip на 1. А делает это так:
1) получает 16 бит предыдущего адреса(чтобы знать к чему прибавлять единицу)
2) переводит в десятичную СС
3) прибавляет 1
4) переводит обратно в двоичную

и тут то вся проблема, если в пункт 1) пришло число вида, например "0000100011100110" (16 разрядов), то после пункта 4) мы получим "100011100111" (12 разрядов). Поэтому мне нужно дописать нули спереди. И я просто генерирую нужное количество и конкатенирую строки. Сейчас всё хорошо, но при выполнении delete [] zero выдаёт ошибку, описанную выше.
Плюс ещё проблема в том, что я не могу передать этот массив в другую функцию с таким прототипом:
void bintoip (char *x1,char *x2);
используя такой вызов:
bintoip(zero,x2);

При выполнении любых действий с x1 в bintoip вызывает исключение:
Необработанное исключение в "0x000000013f6d1627" в "Test_c.exe": 0xC0000005: Нарушение прав доступа при чтении "0x0000000000000000".


Цитата Сообщение от alexcoder Посмотреть сообщение
младшие значения по младшим адресам
itoa делает наоборот - в позиции [0] записан старший разряд, в позиции [15] - малдший.

Я понимаю, что всё выглядит мудрёно, но я буду очень благодарен, если мы найдём решение этой проблемы!

Добавлено через 27 минут
Цитата Сообщение от mutari Посмотреть сообщение
Плюс ещё проблема в том, что я не могу передать этот массив в другую функцию с таким прототипом:
void bintoip (char *x1,char *x2);
используя такой вызов:
bintoip(zero,x2);
При выполнении любых действий с x1 в bintoip вызывает исключение:
Необработанное исключение в "0x000000013f6d1627" в "Test_c.exe": 0xC0000005: Нарушение прав доступа при чтении "0x0000000000000000".
Это уже не актульно, в этом я разобрался.
Осталось только разобраться в освобождении памяти.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
27.07.2011, 00:52     Проблемы при работе с динамическим распределением памяти #16
В принципе здесь несложно вообще избавиться от массива zero, но проблема не в нём, просто она на нём проявляется. А значит надо искать. Наверняка где-то ещё происходит выход за границу буфера, в результате чего целостность "кучи" нарушается.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.07.2011, 00:57     Проблемы при работе с динамическим распределением памяти
Еще ссылки по теме:

C++ Ошибка при работе с динамическим массивом
C++ Выделение и очищение памяти при работе с динамическими строками
C++ Структура с динамическим массивом, предоставление памяти и её очистка

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
mutari
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
27.07.2011, 00:57  [ТС]     Проблемы при работе с динамическим распределением памяти #17
Цитата Сообщение от grizlik78 Посмотреть сообщение
Наверняка где-то ещё происходит выход за границу буфера
Спасибо огромное!! Благодаря этим словам в голове всё прояснилось)) Я же делаю strcat(zero,buf_t);
Получается она к zero дописывает ещё buf_t - и получается выход за пределы. Эх, бывает же..

Спасибо большое вам обоим за помощь!
Yandex
Объявления
27.07.2011, 00:57     Проблемы при работе с динамическим распределением памяти
Ответ Создать тему
Опции темы

Текущее время: 00:10. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru