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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
mutari
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
#1

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

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

Здравствуйте! Возникла проблема при использовании динамической распределении памяти.
Вот код:
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
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.07.2011, 19:38
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Проблемы при работе с динамическим распределением памяти (C++):

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

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

Ошибка при работе с динамическим массивом - C++
Народ можете подсказать пожалуйста, появляется вот такая ошибка при запуски вот такого кода #include &lt;iostream&gt; using namespace...

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

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

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

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
alexcoder
1464 / 678 / 89
Регистрация: 03.06.2009
Сообщений: 3,565
Завершенные тесты: 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;
0
grizlik78
Эксперт С++
1911 / 1443 / 112
Регистрация: 29.05.2011
Сообщений: 3,000
26.07.2011, 21:18 #3
Цитата Сообщение от mutari Посмотреть сообщение
Что я делаю не так?
видимо, полагаете, что sizeof(zero) даёт размер выделенного блока памяти. Увы, это размер указателя (обычно 4 или 8 байт). Переносимых способов определить размер динамически выделенного блока нет. Размер надо запоминать самостоятельно (что можно увидеть у alexcoder)
0
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-разрядного числа.
0
grizlik78
Эксперт С++
1911 / 1443 / 112
Регистрация: 29.05.2011
Сообщений: 3,000
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
mutari
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
26.07.2011, 22:16  [ТС] #6
Спасибо, это помогло - zero[len] = '\0';
Хотя я уже это добавлял, но видимо, надо было до цикла вставить.

Но почему-то вернулась проблема с delete [] zero; - выдаёт ту же ошибку. Почему может такое происходить?
0
grizlik78
Эксперт С++
1911 / 1443 / 112
Регистрация: 29.05.2011
Сообщений: 3,000
26.07.2011, 22:17 #7
Показывай, что получилось.
0
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; - выполнилась без ошибок.
0
grizlik78
Эксперт С++
1911 / 1443 / 112
Регистрация: 29.05.2011
Сообщений: 3,000
26.07.2011, 22:32 #9
C++
1
2
zero = new char [len+1];
zero[len+1] = '\0';
Это выход за границу массива. Для буфера длиной len+1 последний допустимый индекс [len]
0
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]
0
grizlik78
Эксперт С++
1911 / 1443 / 112
Регистрация: 29.05.2011
Сообщений: 3,000
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
mutari
0 / 0 / 0
Регистрация: 26.07.2011
Сообщений: 8
26.07.2011, 23:10  [ТС] #12
А, я сначала недопонял просто. Да, этот вариант без цикла тоже работает, но на delete всё-равно ругается
0
grizlik78
Эксперт С++
1911 / 1443 / 112
Регистрация: 29.05.2011
Сообщений: 3,000
26.07.2011, 23:15 #13
Если вставлено без изменений, то проблема где-то в другом месте. Она может быть даже не в этой функции.
0
alexcoder
1464 / 678 / 89
Регистрация: 03.06.2009
Сообщений: 3,565
Завершенные тесты: 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?
0
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".
Это уже не актульно, в этом я разобрался.
Осталось только разобраться в освобождении памяти.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.07.2011, 00:49
Привет! Вот еще темы с ответами:

Проблемы с динамическим списком - C++
Почему-то выводит ошибку во время выполнения программы &quot;Необработанное исключение в &quot;0x501ed442 (msvcr100d.dll)&quot; в &quot;Динамично.exe&quot;:...

Выделение и очищение памяти при работе с динамическими строками - C++
Всем Доброго времени суток! Пожалуйста укажите на ошибку! #ifndef RECEIPT_H #define RECEIPT_H #include &lt;iostream&gt; using...

При работе начинаются притормаживания (нужна очистка памяти?) - C++
Удачных суток. Встретился с проблемой. Есть функция, предположим: int zuzu(){ short bf; .............. return 0; } Есть...

Двумерный массив с динамическим выделением памяти - C++
Помогите пожалуйста вставить вот в эту вот задачу динамическое выделение памяти: #include &lt;iostream&gt; using namespace std; ...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
27.07.2011, 00:49
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru