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

realloc - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 15, средняя оценка - 4.80
pito211
 Аватар для pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
04.05.2011, 09:51     realloc #1
здраствуйте!

решил накатать такой класс
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. В чё может бытть проблема? Заранее спасибо.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.05.2011, 09:51     realloc
Посмотрите здесь:

malloc, realloc C++
C++ Не выполняется realloc
аналог realloc() в С++ C++
C++ realloc
ошибка realloc C++ C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
04.05.2011, 10:56     realloc #2
добавил
C++
1
2
3
4
#include "stdafx.h"
..............
int main () {
}
всё компильнулось
pito211
 Аватар для pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
04.05.2011, 11:07  [ТС]     realloc #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);
Nameless One
Эксперт С++
 Аватар для Nameless One
5755 / 3404 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
04.05.2011, 11:12     realloc #4
C++
1
2
3
4
if ( _buffer != NULL ) {
 buffer = _buffer;
 buffer[_size - 1] = val;
 }
pito211
 Аватар для pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
04.05.2011, 11:19  [ТС]     realloc #5
ладно наверно по другому сделаю без realloc
Nameless One
Эксперт С++
 Аватар для Nameless One
5755 / 3404 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
04.05.2011, 11:32     realloc #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 и иже с ними
pito211
 Аватар для pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
04.05.2011, 11:43  [ТС]     realloc #7
копировал твою функцию, запутсил вылетело тоже самое. Удивился, заменил int на string нормально работает.
Nameless One
04.05.2011, 12:34
  #8

Не по теме:

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

kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
04.05.2011, 13:29     realloc #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;
будет неправильным, что и требовалось доказать.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
04.05.2011, 13:39     realloc #10
kravam, Конструктор чего прости? Присваивания? При инициализации вызывается конструктор копирования, а не конструктор присваивания (коего кстати в языке вообще нема).
И да кстати о птичках-с. malloc/free не умеют работать с конструкторами/деструкторами, а тут вызывается оператор присваивания, т,к. инициализация (выделение памяти в данном случае) уже было произведено и эти объекты существуют.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
04.05.2011, 13:46     realloc #11
Странно, ей-Богу. Ладно, опустим всё остальное, итак:
Цитата Сообщение от ForEveR Посмотреть сообщение
инициализация (выделение памяти в данном случае) уже было произведено и эти объекты существуют.
Я правильно понял, что "данный случай" это выделение памяти с помощью malloc и прочих *loc?
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
04.05.2011, 13:51     realloc #12
kravam, Ты правильно понял, что я про выделение памяти. Но про *loc корректно сказать не могу (не часто я ими пользуюсь) - единственное в чем я уверен, что он не вызывает конструктора. Следовательно, если он не создан - вызывается конструктор/конструктор копирования, но не опер присваивания. В противовес new кстати. Пример ща попробую предоставить.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
04.05.2011, 14:01     realloc #13
А давайте проверим.
Напишем простенький конструктор копирования, и... и всё. И после
C++
1
2
List k;
p[0]= k;
Обнаружен, что вызван конструктор копирования.
...Я бы и сам взялся написать, но в книге прочёл, что синтаксис конструтора
копирования такой:

C++
1
имя_класса (имя_класса const &источник)
так, а у нас по условию задачи круглых скобок не предусмторен, а предусмотрен знак '='
То есть самописный конструктор копирования сюда никаким боком не включить.
Если можете- напишите, я не могу.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
04.05.2011, 14:01     realloc #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;
}
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
04.05.2011, 14:04     realloc #15
Извините, а как ещё проверить, вызван ли конструктор копирования? Надо писать свой и тогда компилятор подключит его вместо поставляемого. А свой мы легко обнаружим. Правильно ведь?
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
04.05.2011, 14:06     realloc #16
kravam, Ну да. Не написав свой мы просто не увидим что он вызвался, несмотря на то, что если мы его используем компилятор вызовет свой созданный по умолчанию для данного класса (который выполняет побитовое копирование).
pito211
 Аватар для pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
04.05.2011, 14:08  [ТС]     realloc #17
прочитал всё. Понял суть. А как же тогда быть. New и delete заменяют malloc и free а чем заменить realloc? И я правильно понял что реаллок можно использовать только для стандартных сишных типов и больше нигде? конечно можно char использовать вместо string но не хотелось бы прибегать к этому
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
04.05.2011, 14:43     realloc #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;
    }
    }
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
04.05.2011, 15:10     realloc #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);
...и будет неправ. Вопрос: почему?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.05.2011, 15:33     realloc
Еще ссылки по теме:

realloc C++
C++ Функция realloc
C++ Функция realloc

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

Или воспользуйтесь поиском по форуму:
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
04.05.2011, 15:33     realloc #20
kravam, потому что при использовании realloc память может быть довыделена (указатель останется актуальным), и может быть перевыделена, и изначальный указатель станет висячим))
Yandex
Объявления
04.05.2011, 15:33     realloc
Ответ Создать тему
Опции темы

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