186 / 173 / 18
Регистрация: 22.03.2010
Сообщений: 612
1

realloc

04.05.2011, 09:51. Показов 2982. Ответов 21
Метки нет (Все метки)

здраствуйте!

решил накатать такой класс
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
#include <stdlib.h>
 
template <typename TYPE> 
class List
{
private:
    TYPE* buffer;
    size_t _size;
public:
    List() : buffer(NULL), _size(0) {};
    void push(const TYPE &val);
    TYPE pop();
 
 
};
 
template <typename TYPE> 
void List<TYPE>::push(const TYPE &val) {
    _size++;
    TYPE* _buffer = NULL;
    _buffer = (TYPE*) realloc(buffer, sizeof(val) * _size);
 
    if ( _buffer != NULL ) {
        buffer = _buffer;
        buffer[_size] = val;
    }
}
проблема заключается в функции push деббагер в вижуал студио пишет что неправильный указатель в _buffer выделяется, хотя написано всё почти точно так же как в cplusplus.com. Проверял при TYPE=string. В чё может бытть проблема? Заранее спасибо.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.05.2011, 09:51
Ответы с готовыми решениями:

realloc
Доброго времени суток, есть код, в котором динамически выделяется память под массив, затем этот...

realloc
#include &lt;iostream&gt; using namespace std; int main() { int size=0; cout&lt;&lt;&quot;enter size array:...

Не выполняется realloc
Вообщем, не могу понять в чем ошибка, malloc() работает, а realloc() выдает ошибки. Имеется...

ошибка realloc C++
Как изменить размер выделенной памяти? (например выделено 15 байт, как в C++ увеличить размер...

21
быдлокодер
1722 / 909 / 106
Регистрация: 04.06.2008
Сообщений: 5,644
04.05.2011, 10:56 2
добавил
C++
1
2
3
4
#include "stdafx.h"
..............
int main () {
}
всё компильнулось
0
186 / 173 / 18
Регистрация: 22.03.2010
Сообщений: 612
04.05.2011, 11:07  [ТС] 3
Цитата Сообщение от kravam Посмотреть сообщение
добавил
C++
1
2
3
4
#include "stdafx.h"
..............
int main () {
}
всё компильнулось
при компиляции проблем нет. Вот тело программы

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "stdafx.h"
#include <iostream>
#include <string>
 
#include "List.h"
 
using namespace std;
 
 
int main(int argc, char* argv[])
{
 
    List<string> list;
    string str;
    cin >> str;
    list.push(str);
    return 0;
}
вылетает в push после строки buffer[_size] = val; но ещё раньше в строке _buffer = (TYPE*) realloc(buffer, sizeof(val) * _size); в деббагере VS пишет мол неправильный указатель в _buffer. Кстати поправил на buffer[_size-1] но проблема возникает здесь

_buffer = (TYPE*) realloc(buffer, sizeof(val) * _size);
0
Эксперт С++
5825 / 3476 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
04.05.2011, 11:12 4
C++
1
2
3
4
if ( _buffer != NULL ) {
 buffer = _buffer;
 buffer[_size - 1] = val;
 }
0
186 / 173 / 18
Регистрация: 22.03.2010
Сообщений: 612
04.05.2011, 11:19  [ТС] 5
ладно наверно по другому сделаю без realloc
0
Эксперт С++
5825 / 3476 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
04.05.2011, 11:32 6
Не знаю, как у тебя - у меня все работает:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <iostream>
#include <cstdlib>
#include <stdexcept>
 
namespace my
{
    template <class T>
    class stack
    {
    private:
    T* buf;
    size_t sz;
    public:
    stack();
    ~stack();
    void push(const T&);
    T pop();
    size_t size() const;
    bool empty() const;
    };
 
    template <class T>
    stack<T>::stack()
    : buf(NULL), sz(0)
    {
    }
 
    template <class T>
    stack<T>::~stack()
    {
    if(buf)
        free(buf);
    }
 
    template <class T>
    void stack<T>::push(const T& val)
    {
    ++sz;
    if((buf = (T*) realloc(buf, sizeof(T) * sz)) == NULL)
        throw std::runtime_error("Can't allocate memory");
 
    buf[sz - 1] = val;
    }
 
    template <class T>
    T stack<T>::pop()
    {
    if(!sz)
        throw std::runtime_error("Stack is empty");
    
    return buf[--sz];
    }
 
    template <class T>
    size_t stack<T>::size() const
    {
    return sz;
    }
 
    template <class T>
    bool stack<T>::empty() const
    {
    return sz == 0;
    }
}
 
int main()
{
    my::stack<int> stack;
    for(int i = -3; i <= 3; ++i)
    stack.push(i);
 
    while(!stack.empty())
    std::cout << stack.pop() << std::endl;
 
    return 0;
}
И на будущее - в С++ немножко другие средства для работы с памятью, нежели realloc, malloc и иже с ними
2
186 / 173 / 18
Регистрация: 22.03.2010
Сообщений: 612
04.05.2011, 11:43  [ТС] 7
копировал твою функцию, запутсил вылетело тоже самое. Удивился, заменил int на string нормально работает.
0
Nameless One
04.05.2011, 12:34
  #8

Не по теме:

Мистические глюки студии...

0
быдлокодер
1722 / 909 / 106
Регистрация: 04.06.2008
Сообщений: 5,644
04.05.2011, 13:29 9
Дело обстоит так. Рассмотрим строчку:
C++
1
buffer[_size] = val;
Так вот, имеем типичный конструктор присваивания. То есть объекту типа string
C++
1
buffer[_size]
мы присваиваем значение другого объекта типа string; этот объект val
Но вся фишка в том, что объекта
buffer[_size] просто-напросто нет! Потому и возникает ошибка! Под него просто выделена память и всё на этом.
(Важно: конструктор присваивания присваивает значение в уже ИМЕЮЩИЙСЯ объект, в отличие от конструктора копирования.) А realloc объекта не создаёт, а просто выделяет под него место, в отличие от new! Поэтому тут надо работать с new

Небольшой опыт в домашней лаборатории сие подтверждает
++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdlib.h>
#include <stdio.h>
 
class List
{
public:
        List() {printf ("ttttttttttttttt\n");};
};
 
int main () {
 
 
 
 List* p=(List*) malloc(sizeof(k));
 //List* p=new List[(sizeof(k))];
 
 getchar ();
}
Поочерёдно расскоментируя а закомментировывая инструкции выделения памяти, можно обнаружить, что строчка "ttttttttttttttttttttttttt" при одном запуске программы появляется, а при другом нет. То есть в одном случае срабатывает конструктор-объект создаётся (вариант с new) а в другом случае не срабатывает конструктор- объект не создаётся (вариант malloc)

А значит, во втором случае выражение
C++
1
2
List k;
p[0]= k;
будет неправильным, что и требовалось доказать.
1
В астрале
Эксперт С++
8045 / 4802 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
04.05.2011, 13:39 10
kravam, Конструктор чего прости? Присваивания? При инициализации вызывается конструктор копирования, а не конструктор присваивания (коего кстати в языке вообще нема).
И да кстати о птичках-с. malloc/free не умеют работать с конструкторами/деструкторами, а тут вызывается оператор присваивания, т,к. инициализация (выделение памяти в данном случае) уже было произведено и эти объекты существуют.
1
быдлокодер
1722 / 909 / 106
Регистрация: 04.06.2008
Сообщений: 5,644
04.05.2011, 13:46 11
Странно, ей-Богу. Ладно, опустим всё остальное, итак:
Цитата Сообщение от ForEveR Посмотреть сообщение
инициализация (выделение памяти в данном случае) уже было произведено и эти объекты существуют.
Я правильно понял, что "данный случай" это выделение памяти с помощью malloc и прочих *loc?
1
В астрале
Эксперт С++
8045 / 4802 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
04.05.2011, 13:51 12
kravam, Ты правильно понял, что я про выделение памяти. Но про *loc корректно сказать не могу (не часто я ими пользуюсь) - единственное в чем я уверен, что он не вызывает конструктора. Следовательно, если он не создан - вызывается конструктор/конструктор копирования, но не опер присваивания. В противовес new кстати. Пример ща попробую предоставить.
1
быдлокодер
1722 / 909 / 106
Регистрация: 04.06.2008
Сообщений: 5,644
04.05.2011, 14:01 13
А давайте проверим.
Напишем простенький конструктор копирования, и... и всё. И после
C++
1
2
List k;
p[0]= k;
Обнаружен, что вызван конструктор копирования.
...Я бы и сам взялся написать, но в книге прочёл, что синтаксис конструтора
копирования такой:

C++
1
имя_класса (имя_класса const &источник)
так, а у нас по условию задачи круглых скобок не предусмторен, а предусмотрен знак '='
То есть самописный конструктор копирования сюда никаким боком не включить.
Если можете- напишите, я не могу.
1
В астрале
Эксперт С++
8045 / 4802 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
04.05.2011, 14:01 14
Что ж. Нет, я был не прав. *loc так же создают объект, просто не вызывая конструктора.

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
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <cstdlib>
#include <iostream>
 
struct some_struct
{
    some_struct():t(0)
    {
        std::cout << "Default constructor" << '\n';
    }
    some_struct(int t_):t(t_)
    {
        std::cout << "Constructor with param" << '\n';
    }
    some_struct(const some_struct& other):t(other.t)
    {
        std::cout << "Copy constructor" << '\n';
    }
    some_struct& operator =(const some_struct& other)
    {
        std::cout << "Assigned operator" << '\n';
        t = other.t;
        return *this;
    }
    ~some_struct()
    {
        std::cout << "Destructor" << '\n';
    }
    int t;
};
 
int main()
{
    some_struct* arr = static_cast<some_struct*>(malloc(sizeof(some_struct)));
    *arr = some_struct(5);
    free(arr);
    some_struct* other_arr = new some_struct;
    *other_arr = some_struct(10);
    delete other_arr;
    return 0;
}
1
быдлокодер
1722 / 909 / 106
Регистрация: 04.06.2008
Сообщений: 5,644
04.05.2011, 14:04 15
Извините, а как ещё проверить, вызван ли конструктор копирования? Надо писать свой и тогда компилятор подключит его вместо поставляемого. А свой мы легко обнаружим. Правильно ведь?
1
В астрале
Эксперт С++
8045 / 4802 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
04.05.2011, 14:06 16
kravam, Ну да. Не написав свой мы просто не увидим что он вызвался, несмотря на то, что если мы его используем компилятор вызовет свой созданный по умолчанию для данного класса (который выполняет побитовое копирование).
1
186 / 173 / 18
Регистрация: 22.03.2010
Сообщений: 612
04.05.2011, 14:08  [ТС] 17
прочитал всё. Понял суть. А как же тогда быть. New и delete заменяют malloc и free а чем заменить realloc? И я правильно понял что реаллок можно использовать только для стандартных сишных типов и больше нигде? конечно можно char использовать вместо string но не хотелось бы прибегать к этому
0
В астрале
Эксперт С++
8045 / 4802 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
04.05.2011, 14:43 18
pito211, Вектором пользоваться. Стрингом. Нету замены реаллоку в С++. Однако если посмотреть в сторону STL в частности вектор и т.д. можно понять что замена все же есть, хоть и довольно тяжелая.

Добавлено через 26 минут
Реализация reserve в векторе в GCC 4.4.5. Почти realloc по сути.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  template<typename _Tp, typename _Alloc>
    void
    vector<_Tp, _Alloc>::
    reserve(size_type __n)
    {
      if (__n > this->max_size())
    __throw_length_error(__N("vector::reserve"));
      if (this->capacity() < __n)
    {
      const size_type __old_size = size();
      pointer __tmp = _M_allocate_and_copy(__n,
         _GLIBCXX_MAKE_MOVE_ITERATOR(this->_M_impl._M_start),
         _GLIBCXX_MAKE_MOVE_ITERATOR(this->_M_impl._M_finish));
      std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
            _M_get_Tp_allocator());
      _M_deallocate(this->_M_impl._M_start,
            this->_M_impl._M_end_of_storage
            - this->_M_impl._M_start);
      this->_M_impl._M_start = __tmp;
      this->_M_impl._M_finish = __tmp + __old_size;
      this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;
    }
    }
1
быдлокодер
1722 / 909 / 106
Регистрация: 04.06.2008
Сообщений: 5,644
04.05.2011, 15:10 19
Что касается realloc, то на самом деле существует незаметная трудность, которые сопряжены с его использованием. Рискну предположить, что неопытный новичёк сделает так:

C++
1
2
3
4
5
6
7
int* p_0;
p= calloc (100, sizeof(int));
//Здесь некоторый код, после которого необходимо изменить блока, на который указывает p_0
 
int* p_1;
p_1= realloc (p_0, 200);
free (p_0);
...и будет неправ. Вопрос: почему?
0
Эксперт С++
5052 / 3113 / 271
Регистрация: 11.11.2009
Сообщений: 7,045
04.05.2011, 15:33 20
kravam, потому что при использовании realloc память может быть довыделена (указатель останется актуальным), и может быть перевыделена, и изначальный указатель станет висячим))
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.05.2011, 15:33
Помогаю со студенческими работами здесь

Realloc и цикл
Здравствуйте, у меня возникает проблема с этой функцией когда поступают на вход равные n n2. На...

Альтернатива realloc ?
Ищу способ динамически расширять массив объектов. В с++ использую new и delete, а перемешивать с...

Malloc realloc и C++
Подскажите, в C++ 11 выделение памяти по прежнему &quot;нормально&quot; выделять с помощью malloc и изменять...

аналог realloc() в С++
Здравствуйте. собственно вопрос:-существует ли таковой?


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru