Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> new delete и указатель на структуру 
:(
    Опции темы
jeff
Дата 24.1.2012, 16:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 24.1.2012

Репутация: нет
Всего: нет



Всем привет!

Код и ниже 2 вопрома по нему

Код
#include "stdafx.h"

typedef struct persontag
{
 int height;
 int weight;
} person, *pperson;

void changePerson2(person* p)
{
 p->weight = 100;
 p->height = 100;
}

int _tmain(int argc, _TCHAR* argv[])
{
 pperson pp; 
 pp = pperson(new pperson);

 changePerson2(pp);
 delete pp;
 return 0;

}


Все работает до вопроса N2

1) Почему не работает просто new pperson , а приходится приводить тип
2) На delete  pp программа виснет. Что не так?

Всем спасибо...............


Модератор: не забываем пользоваться кнопочкой "Код"

Это сообщение отредактировал(а) bsa - 24.1.2012, 17:15
PM MAIL   Вверх
azesmcar
Дата 24.1.2012, 17:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата(jeff @  24.1.2012,  16:59 Найти цитируемый пост)
1) Почему не работает просто new pperson , а приходится приводить тип

потому-что надо создавать объект а не указатель.
Код

pperson pp = new person;


Цитата(jeff @  24.1.2012,  16:59 Найти цитируемый пост)
2) На delete  pp программа виснет. Что не так?

проблема в том же.
PM   Вверх
borisbn
Дата 24.1.2012, 17:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(jeff @  24.1.2012,  16:59 Найти цитируемый пост)
new pperson

данная конструкция выделяет память под указатель (4 байта на 32-х битной ОС и 8 - на 64-х битной), а не под структуру, и возвращает указатель на указатель на структуру, а не указатель на структуру
сделай так, и будет тебе счастье smile
Код
pp = new person;

и можешь спокойно делать
Цитата(jeff @  24.1.2012,  16:59 Найти цитируемый пост)
 delete pp;


и пользуйся кнопочкой код



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
jeff
Дата 24.1.2012, 17:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 24.1.2012

Репутация: нет
Всего: нет



Все понял, спасибо, здОрово.

Добавлено через 9 минут и 23 секунды
Осталось, все-таки непонятным, почему в "правильном" и "неправильном" корректно отработалпа функция changePerson2. ?
С указателем и с указателем на указатель в качестве параметра..
PM MAIL   Вверх
bsa
Дата 24.1.2012, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



jeff, это тебе кажется, что "корректно". Результат ошибки может проявиться значительно позже.
Никогда не делай "typedef something *psomething". Значительно проще писать каждый раз звездочку для создания указателя. Да и ошибок будет меньше. Например: "const something *x" и "const psomething x" - это разные вещи!!!
PM   Вверх
azesmcar
Дата 24.1.2012, 17:45 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата(jeff @  24.1.2012,  17:22 Найти цитируемый пост)
Осталось, все-таки непонятным, почему в "правильном" и "неправильном" корректно отработалпа функция changePerson2. ?

А с чего ты взял, что она отрабатывала корректно?

Добавлено через 38 секунд
Цитата(bsa @  24.1.2012,  17:45 Найти цитируемый пост)
Результат ошибки может проявиться значительно позже.

И совершенно в другом месте smile 
PM   Вверх
jeff
Дата 25.1.2012, 07:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 24.1.2012

Репутация: нет
Всего: нет



Я неопытный.

 
Код

pp = new person;
 changePerson2(pp);


и

Код

 pp = pperson(new pperson);
 changePerson2(pp);



дают одинаковый(и предсказуемый) результат работы changePerson2 

Можно ли считать что при pp = pperson(new pperson); выполняется как бы инициализация массива person* и в функцию передается первый(и единственный)  элемент массива, и поэтому changePerson2 работает?

То что при освобождении памяти возникают проблемы, уже понял, я  говорю только о функции changePerson2

PM MAIL   Вверх
azesmcar
Дата 25.1.2012, 08:52 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



Цитата(jeff @  25.1.2012,  07:36 Найти цитируемый пост)
дают одинаковый(и предсказуемый) результат работы changePerson2 

Нет, это они в этот раз дали одинаковый результат, разница в том, что первый вариант по стандарту должен работать всегда, в то время как второй может вызвать ошибку записи, логическую ошибку где-то в другом участке кода или землетрясение в Бурунди, результат совершенно непредсказуем.

Это сообщение отредактировал(а) azesmcar - 25.1.2012, 08:53
PM   Вверх
borisbn
Дата 25.1.2012, 09:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



jeff, посмотри внимательно этот код
http://liveworkspace.org/code/6c737cc1d8e5...635a191a48ca81f
и представь, что arr описан как int arr[ 1 ];
в твоём случае происходит примерно то же самое.
ты выделил память под указатель, т.е. 4 байта (на 32-х разрядной ОС), а считаешь, что выделил память под структуру, т.е. вторая запись ( p->height = 100; ) ведётся по неразрешённой (не выделенной для этих целей) памяти.
Если есть желание поэкпериментировать и убедиться в правильности этого
Цитата(azesmcar @  25.1.2012,  08:52 Найти цитируемый пост)
 второй может вызвать ошибку записи, логическую ошибку где-то в другом участке кода или землетрясение в Бурунди, результат совершенно непредсказуем.

то измени структуру след. образом
Код

typedef struct persontag
{
 char dummy[ 10 * 1024 * 1024 ];
 int height;
 int weight;
} person, *pperson;


Добавлено через 1 минуту и 25 секунд
и оставь свой первоначальный код без изменений. результат должен быть примерно как сказал azesmcar


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
bsa
Дата 25.1.2012, 10:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



jeff, смотри, типичный размер твоей структуры 8 байт. Типичный размер указателя - 4 байта. оператор new выделяет под указатель 4 байта памяти и возвращает адрес начала выделенной области памяти. ты с ними работаешь. Потом ты решил еще выделить память. Так как менеджер памяти считает, что занято только 4 байта, то он выделяет сразу за ними. В итоге, меняя данные в новой выделенной области ты портишь в старой... Но это при такой простой работе менеджера памяти. А теперь представим, что менеджер памяти выделяет какую-то область, в начало ее пишет какие-то служебные данные, а возвращает уже адрес за ними. Таким образом, после второго выделения ты можешь потереть служебные данные. И ошибка возникнет при попытке освобождения памяти или еще одного выделения...
PM   Вверх
jeff
Дата 25.1.2012, 12:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 24.1.2012

Репутация: нет
Всего: нет



Спасибо всем ответившим, все разъяснили, все понял.  С++ коварен, однако
PM MAIL   Вверх
borisbn
Дата 25.1.2012, 12:51 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(jeff @  25.1.2012,  12:48 Найти цитируемый пост)
С++ коварен, однако

 smile 
Есть простое правило: никогда не используй приведение типов, за исключением:
1) Без этого вообще никак не обойтись
2) Ты на 0x64% знашь, что ты делаешь и как это будет работать 


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

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


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1185 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.