Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/8: Рейтинг темы: голосов - 8, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
1

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

26.07.2011, 19:38. Показов 1500. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте! Возникла проблема при использовании динамической распределении памяти.
Вот код:
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.
Что я делаю не так? Заранее спасибо!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.07.2011, 19:38
Ответы с готовыми решениями:

Shared_ptr и классы с динамическим распределением памяти
Корректен ли класс? Не будет каких-нибудь проблем с памятью или других? Допустим, это заготовка...

Ошибка при работе с динамическим массивом
ошибка heap corruption detected: after normal block &quot;#355&quot; Ситуация такая, научился работать с...

Ошибка при работе с динамическим массивом
Народ можете подсказать пожалуйста, появляется вот такая ошибка при запуски вот такого кода...

Ошибка повреждения кучи при работе с динамическим стеком
код выдает ошибку повреждения кучи class pixel1 { public: pixel1(int i, int j, int way, int...

16
1779 / 757 / 153
Регистрация: 03.06.2009
Сообщений: 5,927
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;
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
26.07.2011, 21:18 3
Цитата Сообщение от mutari Посмотреть сообщение
Что я делаю не так?
видимо, полагаете, что sizeof(zero) даёт размер выделенного блока памяти. Увы, это размер указателя (обычно 4 или 8 байт). Переносимых способов определить размер динамически выделенного блока нет. Размер надо запоминать самостоятельно (что можно увидеть у alexcoder)
0
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-разрядного числа.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
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 Посмотреть сообщение
Второй вопрос отпал - спасибо! Помогло, когда убрал квадратные скобки.
Как раз с квадратными скобками правильно, а без них — нет.
0
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
26.07.2011, 22:16  [ТС] 6
Спасибо, это помогло - zero[len] = '\0';
Хотя я уже это добавлял, но видимо, надо было до цикла вставить.

Но почему-то вернулась проблема с delete [] zero; - выдаёт ту же ошибку. Почему может такое происходить?
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
26.07.2011, 22:17 7
Показывай, что получилось.
0
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; - выполнилась без ошибок.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
26.07.2011, 22:32 9
C++
1
2
zero = new char [len+1];
zero[len+1] = '\0';
Это выход за границу массива. Для буфера длиной len+1 последний допустимый индекс [len]
0
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]
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
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.
0
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
26.07.2011, 23:10  [ТС] 12
А, я сначала недопонял просто. Да, этот вариант без цикла тоже работает, но на delete всё-равно ругается
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
26.07.2011, 23:15 13
Если вставлено без изменений, то проблема где-то в другом месте. Она может быть даже не в этой функции.
0
1779 / 757 / 153
Регистрация: 03.06.2009
Сообщений: 5,927
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?
0
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".
Это уже не актульно, в этом я разобрался.
Осталось только разобраться в освобождении памяти.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
27.07.2011, 00:52 16
В принципе здесь несложно вообще избавиться от массива zero, но проблема не в нём, просто она на нём проявляется. А значит надо искать. Наверняка где-то ещё происходит выход за границу буфера, в результате чего целостность "кучи" нарушается.
0
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
27.07.2011, 00:57  [ТС] 17
Цитата Сообщение от grizlik78 Посмотреть сообщение
Наверняка где-то ещё происходит выход за границу буфера
Спасибо огромное!! Благодаря этим словам в голове всё прояснилось)) Я же делаю strcat(zero,buf_t);
Получается она к zero дописывает ещё buf_t - и получается выход за пределы. Эх, бывает же..

Спасибо большое вам обоим за помощь!
0
27.07.2011, 00:57
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.07.2011, 00:57
Помогаю со студенческими работами здесь

Ошибка с памятью при работе с динамическим двумерным массивом
Вроде всё правильно, но в ходе работы программа выдаёт ошибку(на скрине). Дело в двумерном...

Ошибка при работе с двумерным динамическим массивом, созданным через функцию
Доброго времени суток. У меня проблема при работе с динамическим массивом, созданным через функцию....

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

утечка памяти при работе с матрицей
нужно сформировать массив, в который записываем 0, если все элементы столбца матрицы равны нулю, в...


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

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru