16.08.2018, 00:17 [+3 UTC]
в нашей команде: 2 913 чел. | участники онлайн: 0 (рекорд: 21)

:: РЕГИСТРАЦИЯ

:: задать вопрос

:: все разделы

:: правила

:: новости

:: участники

:: доска почёта

:: форум

:: блоги

:: поиск

:: статистика

:: наш журнал

:: наши встречи

:: наша галерея

:: отзывы о нас

:: поддержка

:: руководство

Версия системы:
7.47 (16.04.2018)

Общие новости:
13.04.2018, 10:33

Форум:
15.08.2018, 01:47

Последний вопрос:
13.08.2018, 01:44

Последний ответ:
12.08.2018, 20:20

Последняя рассылка:
15.08.2018, 21:45

Писем в очереди:
0

Мы в соцсетях:

Наша кнопка:

RFpro.ru - здесь вам помогут!

Отзывы о нас:
29.08.2010, 08:10 »
Зайцев Геннадий Викторович
Спасибо за ответ. [вопрос № 179789, ответ № 262895]
04.12.2009, 04:30 »
Brutuss
Спасибо большое! Обязательно учту ваши советы во время покупки! [вопрос № 174730, ответ № 257254]
22.04.2010, 15:39 »
Botsman
Спасибо огромное. То, что надо! [вопрос № 177976, ответ № 260959]

РАЗДЕЛ • С / С++

Создание программ на языках C и C++.

[администратор рассылки: Андрей Кузнецов aka Dr_Andrew (Старший модератор)]

Лучшие эксперты в этом разделе

solowey
Статус: Студент
Рейтинг: 64
CradleA
Статус: Профессор
Рейтинг: 62
mklokov
Статус: 6-й класс
Рейтинг: 23

Перейти к консультации №:
 

Консультация онлайн # 187140
Раздел: • С / С++
Автор вопроса: Сергей Бендер (Профессионал)
Отправлена: 29.01.2013, 20:55
Поступило ответов: 2

Здравствуйте! Прошу помощи в следующем вопросе:

Мне принесли программу, в которой написано (M$ Visual C++ 2005):

int *mas=new int[];

Она успешно компилируется. Объясните, что это значит? Сколько как и сколько тут выделяется памяти?

Ещё один связанный вопрос. Раньше -- на Паскале -- я бы просто сделал memavail. Про С я где-то прочитал, что такой функции нет. А как же в C/C++ контролируют утечки памяти?

Состояние: Консультация закрыта

Здравствуйте, Сергей Бендер!

Именно в VS2005 это действительно компилируется, хотя, по хорошему, не должно.
Осмелюсь предположить, что данный компилятор трактует new int[] как new int[0]. Последнее допустимо, хотя и бесполезно.

Для контроля утечек памяти можно собирать проект с отладочной информацией и использовать Valgrind под Linux или Dr. Memory под Windows. И, да, работа с голыми указателями в C++ без очень уважительной причины -- дурной тон. Используют обёртки над ними -- т.н. умные указатели.


Консультировал: Чекменёв Александр Анатольевич (Профессор)
Дата отправки: 30.01.2013, 00:25

Рейтинг ответа:

0

[подробно]

Сообщение
модераторам

Отправлять сообщения
модераторам могут
только участники портала.
ВОЙТИ НА ПОРТАЛ »
регистрация »

Ответ # 272061 от Micren

Здравствуйте, Сергей Бендер!
Если Вы пользуетесь продуктами от MS, утечку памяти детектировать можно следующим образом.

#ifdef _DEBUG
#include <crtdbg.h>
#endif

int main()
{
#ifdef _DEBUG
	_CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
#endif
	const int SIZE=10;
	// Выделяем память
	int* arr=new int[SIZE];
	
	// Что-то делаем
	for(int i=0;i<SIZE;++i)
	{
		arr[i]=i;
	}

	// Забыли освободить
	// delete[] arr;
}


В данном случае не освобождается память под массив. Имеем такой вывод отладки:
...
Detected memory leaks!
Dumping objects ->
{68} normal block at 0x00757DD8, 40 bytes long.
 Data: <                > 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 
Object dump complete.
Программа "[4880] 187140.exe" завершилась с кодом 0 (0x0).


Консультировал: Micren
Дата отправки: 30.01.2013, 13:09

5
нет комментария
-----
Дата оценки: 31.01.2013, 22:05

Рейтинг ответа:

0

[подробно]

Сообщение
модераторам

Отправлять сообщения
модераторам могут
только участники портала.
ВОЙТИ НА ПОРТАЛ »
регистрация »

Мини-форум консультации № 187140

Посетитель

ID: 390430

# 1

= общий = | 29.01.2013, 21:07 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Сергей Бендер:

запись с таким выделением памяти - явно ошибочна. в 2010 студии такую запись скомпилировать не удалось.
Попробуйте,очистить весь проект и собрать заново. Может он собирает старые значение, где не было такой ошибки.
Посмотреть сколько памяти "кушает" эта переменная можно в дебагере. Даже интересно, сколько она занимает места:).
В С/С++ утечку памяти контролирует только сам программист(то есть как он пишет).Среда утечку памяти не контролирует. Поэтому в С/С++ утечка памяти- частая и очень сложно вылавливаемая ошибка.

int *mas=new int[5];

...

delete[] mas;

mas = 0;



Было бы более логично:)

• Отредактировал: [неизвестный]
• Дата редактирования: 29.01.2013, 21:16


Посетитель

ID: 181465

# 2

= общий = | 30.01.2013, 07:12 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

В 6-й студии скомпилировалось, выделило 0 памяти.

Есть пара функций, IsBadReadPtr, IsBadWrritePtr - но я ими никогда не пользовался, не знаю, насколько хорошо они работают. А при правильной организации программы память обычно не течёт smile .
Про дурной тон ещё добавлю: если пользуетесь указателями, то лучше это делать в отдельном классе, где доступ к этоту указателю закрыт, и сам класс следит, чтобы память освобождалась на выходе(в деструкторе/в чистилке). Т.е. примерно так:

class CMy
{
protected:
	int *m_piMas;
public:
	CMy();
	virtual ~CMy();
	bool Create(unsigned int iSize);
	void Clear();
	bool Get(int idx, int &iData);
	bool Set(int idx, int iData);
};

CMy::CMy()
{
	m_piMas = NULL;
}

CMy::~CMy()
{
	Clear();
}

bool CMy::Create(unsigned int iSize)
{
	Clear();
	m_piMas = new int[iSize];
	return (NULL != m_piMas);
}

void CMy::Clear()
{
	if(m_piMas)
	{
		delete[]m_piMas;
		m_piMas = NULL;
	}
}

bool CMy::Get(int idx, int &iData)
{
	if(m_piMas)
	{
		iData = m_piMas[idx];
		return true;
	}
	return false;
}

bool CMy::Set(int idx, int iData)
{
	if(m_piMas)
	{
		m_piMas[idx] = iData;
		return true;
	}
	return false;
}


Возможно это будет выглядеть слегка громоздко по сравнению с:

int *mas=new int[iSize];
delete[]mas;

smile

но, "лучше день потерять" честное слово, потому что в проектах такой код-обёртка:
1. будет смотреться очень маленьким по сравнению с остальным
2. сбережёт кучу времени и нервов
3. его легко модифицировать, не затрагивая остальную программу

я не стал в класс добавлять переменную размера массива, чтобы пример получился по-меньше. Комменатрии и правки приветствуются, потому как я часто в общих случаях пользуюсь примерно такой схемой работы с указателями в классах. smile




Сергей Бендер
Профессионал

ID: 304622

# 3

= общий = | 31.01.2013, 21:45 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

© Цитата:
Осмелюсь предположить, что данный компилятор трактует new int[] как new int[0]. Последнее допустимо, хотя и бесполезно.


Хм-м. Смешно. Т.е. я так понимаю в диспетчере памяти создаётся запись, но длина у него нулевая.

Я тут эксперимент сделал. Строка
int *mas=new int[-1];
тоже успешно откопилировалась. Странно. Хотя компилятор мог просто превратить знаковое число в беззнаковое.

© Цитата:
Для контроля утечек памяти можно собирать проект с отладочной информацией и использовать Valgrind под Linux или Dr. Memory под Windows.


Пока то да сё, поставлю, научюсь пользоваться. Могу я вас попросить: посмотрите сами (например с помощью этого Dr. Memory) сколько же выделяется памяти при new int[]? А сколько при new int[-1]?

© Цитата:
И, да, работа с голыми указателями в C++ без очень уважительной причины -- дурной тон. Используют обёртки над ними -- т.н. умные указатели.


Это, наверно, так. Но мне поручили вести C/C++ первокурсникам (и сам многое для себя открываю). Не знаю, можно ли "голые" указатели обойти. Боюсь "умных" сразу не осилят.

Сергей Бендер
Профессионал

ID: 304622

# 4

= общий = | 31.01.2013, 22:04 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

Спасибо.

А такого чтобы в самой программе, по ходу работы, а не после окончания всё-таки нет?
(Я всё думаю об эквиваленте паскалевского memavail.)

Сергей Бендер
Профессионал

ID: 304622

# 5

= общий = | 31.01.2013, 22:10 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

© Цитата:
запись с таким выделением памяти - явно ошибочна. в 2010 студии такую запись скомпилировать не удалось.


Хм-м. У меня версия 2005. У студентов -- 2008. В них копилируется.

А в старом Borland C -- ошибка.

© Цитата:
Попробуйте,очистить весь проект и собрать заново. Может он собирает старые значение, где не было такой ошибки.


Нет. Это абсолютно чистый новый проект, типа Win32 Console.

Сергей Бендер
Профессионал

ID: 304622

# 6

= общий = | 31.01.2013, 22:15 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

© Цитата:
выделило 0 памяти.


Как узнали?

© Цитата:
но, "лучше день потерять" честное слово, потому что в проектах такой код-обёртка:


"Если бы у нас был ротвейлер! Если бы у нас была перчатка той женщины! Если бы собака сразу взяла след!"
(Мюллер, "17 мнгновений весны")

Для первокурсников, многие из которых, плохо понимают даже if и циклы -- это IMHO неподъёмно.

Чекменёв Александр Анатольевич
Профессор

ID: 399103

# 7

= общий = | 01.02.2013, 00:13 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Сергей Бендер:

© Цитата: Сергей Бендер
Т.е. я так понимаю в диспетчере памяти создаётся запись, но длина у него нулевая.

Вроде того. Т.е. удалить её можно(и нужно, т.к. метаданные -- информация о размере массива, например, -- в памяти, в общем случае, лежат), а писать в неё -- нет. Стандарт(пункт 5.3.4/7) позволяет:
© Цитата:
When the value of the expression in a noptr-new-declarator is zero, the allocation function is called to allocate an array with no elements.


© Цитата: Сергей Бендер
Я тут эксперимент сделал. Строка
int *mas=new int[-1];
тоже успешно откопилировалась. Странно. Хотя компилятор мог просто превратить знаковое число в беззнаковое.

Это и происходит. Ведь соответствующий аргумент имеет тип std::size_t. А
std::cout << static_cast<std::size_t>(-1);
даёт
4294967295

Попробуйде запустить программу со строкой
new int[-1];
Должно бросить исключение -- выделить памяти во всё адресное пространство не дадут. А какое-нибудь -static_cast<std::size_t>(-1) должно работать. Т.е.
new int[-4294967295];
создаст массив в 1 элемент. Но это уже рассуждение за пределами языка, разумеется.

© Цитата: Сергей Бендер
Могу я вас попросить: посмотрите сами (например с помощью этого Dr. Memory) сколько же выделяется памяти при new int[]? А сколько при new int[-1]?

Прямо сейчас, увы, не могу посмотреть. Но вообще new int[-1] должен создать массив в std::size_t(-1) интов, плюс (вообще говоря, зависящие от реализации) метаданные. new int[0], соответственно, лишь метаданные.

© Цитата: Сергей Бендер
Но мне поручили вести C/C++ первокурсникам (и сам многое для себя открываю). Не знаю, можно ли "голые" указатели обойти. Боюсь "умных" сразу не осилят.

А, я-то думал, вам проект дали поддерживать. Тут, конечно, без голых не обойтись. Тем более, что умные -- не более чем ~бустовские(Boost library) классы. Т.е. они введены в язык посредством стандартной библиотеки(их в каком-нибудь <memory> можно посмотреть(а то и поправить :))), а не "на уровне языка".

• Отредактировал: [неизвестный]
• Дата редактирования: 01.02.2013, 11:17


Посетитель

ID: 181465

# 8

= общий = | 01.02.2013, 07:21 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

© Цитата: Сергей Бендер
int *mas=new int[-1];
тоже успешно откопилировалась. Странно. Хотя компилятор мог просто превратить знаковое число в беззнаковое.


О, интересно! smile Как я сам не догадался раньше до такого? Не, по отрицательным индексам я ходил... но вот отрицательное количество памяти не выделял smile Однако ж, VC6 откомпилировало, но на вход приняло как беззнаковое целое, что и ожидалось.

© Цитата: Сергей Бендер
Как узнали?

В дамп памяти посмотрел в отладке.

© Цитата: Сергей Бендер
Для первокурсников, многие из которых, плохо понимают даже if и циклы -- это IMHO неподъёмно.

Можно ещё упростить. Можно начать вообще с простейшего варианта, а потом на примерах обшивать код классом и новыми методами. Кстати, в жизни ровно так и происходит, у меня например. За пять минут делаю базовый класс. Потом постепенно в нём что-то правится по ходу разработки (многим покажется неправильным такой подход, но я работаю несколько в другой плоскости, поэтому там это наиболее правильный вариант разработки).

© Цитата: Сергей Бендер
Но мне поручили вести C/C++ первокурсникам

Да, этому не позавидуешь... smile

 

Возможность оставлять сообщения в мини-форумах консультаций доступна только после входа в систему.
Воспользуйтесь кнопкой входа вверху страницы, если Вы зарегистрированы или пройдите простую процедуру регистрации на Портале.

Яндекс Rambler's Top100

главная страница | поддержка | задать вопрос

Время генерирования страницы: 0.19555 сек.

© 2001-2018, Портал RFPRO.RU, Россия
Калашников О.А.  |  Гладенюк А.Г.
Версия системы: 7.47 от 16.04.2018