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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> освобождение памяти 
V
    Опции темы
CTapMex
Дата 15.1.2010, 08:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Приветствую. 
тема вроде избитая, но вот нашел интересный момент.
исходные данные  - VC++ 2008 SP1

код такого содержания
Код

wchar_t *Name = null;
//тут у нас при наличии данных в реестре идет выделение памяти под Name  
int len=rGetValue(hPluginRegistry, 'name', Name);
if (len<=1)  
  Name = L"default";

далее некоторые действия с Name, не меняющие его содержимого
delete[] Name;



ошибка происходит в последней строчке, при выполнении выше  Name = L"default";
на сколько я понимаю , при компилировании строка помещается в область данных, и при условии len<=1 дается ссылка на эту область.
тут видимо и должна происходить ошибка, ведь память вроде как и не выделялась

но вот есть такой момент
запускаю этот код на WinXP SP3 хоть под отладчиком, хоть уже в релизе - все как часы работает. 
Но вот стоит запустить это на WinXp SP2  (не на всех компах срабатывает) , либо на Win7 (опять же через раз ) то выскакивает ошибка "Runtime Error! ...."
да и когда тестировал в отладчике на win7  ошибка не возникала, соберу релиз - появилась. пересоберу релиз без изменений - работает.

тут соответственно вопрос
мой код все таки некорректен?  или это уже ошибка компилятора/библиотек которые то корректно отрабатывают удаление памяти, то некорректно
PM MAIL   Вверх
artsb
Дата 15.1.2010, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

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



Лично я считаю, что должно быть так:
Код

wchar_t *Name = NULL;

int len=rGetValue(hPluginRegistry, 'name', Name);
if (len<=1) {
  Name = new wchar_t[wcslen(L"default")];
  wcscpy(Name, L"default");
}

if(Name)
 delete [] Name;

Вы нигде не выделяете память и пытаетесь потом что-то удалить. И если пару раз "прокатило", это не значит, что так можно  smile 

Это сообщение отредактировал(а) artsb - 15.1.2010, 09:45


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
CTapMex
Дата 15.1.2010, 09:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



artsb
спасибо за пример, я предполагал по другом это решить. но у тебя решение лучше.

ну пару раз прокатило - но оно прокатывало то интересно как  то - на разных компах по разному. у себя на компе я ни разу как не пытался не мог заставить появится ошибке. 
а уж на win7 через раз. 
у меня стойкое впечатление, что эту ситуацию по разному обрабатывают разные версии ситемных библиотек. или компилятор
PM MAIL   Вверх
Dem_max
Дата 15.1.2010, 10:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Наверное код нужно подправить  smile 
Код

wchar_t *Name = NULL;
int MAX_LEN = 255;

Name = new wchar_t[MAX_LEN];

int len=rGetValue(hPluginRegistry, 'name', Name);
if (len<=1) {
  wcscpy(Name, L"default");
}

if(Name)
 delete [] Name;




--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
CTapMex
Дата 15.1.2010, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Dem_max

в моем случае твой вариант не вариант.
в процедуре rGetValue идет чтение строкового значения из реестра. а оно может быть по размеру любым. по этому выделение памяти  идет по факту.
PM MAIL   Вверх
artsb
Дата 15.1.2010, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

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



Цитата(CTapMex @  15.1.2010,  09:52 Найти цитируемый пост)
а уж на win7 через раз.

У меня ни разу не прокатило smile

По поводу вашего случая.
ИМХО в этом случае, компилер смотрит что строка константная и пихает её в ресурсы, а после этой операции:
Код

Name = L"default";

в Name хранится указатель на строку, которую вы не создавали. А потом вы пытаетесь её удалить  smile 
В этом случае, нужно убрать
Код

delete [] Name;

и должно работать. ИМХО

ЗЫ поправьте если что smile


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
CTapMex
Дата 15.1.2010, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



artsb
все правильно говоришь. но вот работало у меня.
хотя я уже ни в чем не уверен. вечером еще раз проверю на win7
PM MAIL   Вверх
Dem_max
Дата 15.1.2010, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(CTapMex @  15.1.2010,  10:20 Найти цитируемый пост)
в процедуре rGetValue

Значит в процедуре выделяется память ?


Цитата(artsb @  15.1.2010,  10:26 Найти цитируемый пост)
в Name хранится указатель на строку, которую вы не создавали. А потом вы пытаетесь её удалить   В этом случае, нужно убрать
ЗЫ поправьте если что

Все верно.
Для новичка эта вещь не очевидная, если он ее не поймет то дальше  можеть быть крах программы. И человек просто запарится искать свой косяк.



--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
CTapMex
Дата 15.1.2010, 12:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(Dem_max @ 15.1.2010,  13:28)
Цитата(CTapMex @  15.1.2010,  10:20 Найти цитируемый пост)
в процедуре rGetValue

Значит в процедуре выделяется память ?

да, в первом посте это указано


PM MAIL   Вверх
artsb
Дата 15.1.2010, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

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



CTapMex, ну вы понимаете, что в функции не может выделиться память для Name? Вы передаёте нулевой указатель и все. Память выделяется под указатель, который является параметром функции. Т.е.
Код

int rGetValue(..., ..., wchar_t *ff) {
// здесь ff = NULL
ff = new wchar_t[5];
// Name не будет указывать туда же куда и ff
}


Это сообщение отредактировал(а) artsb - 15.1.2010, 12:18


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
CTapMex
Дата 15.1.2010, 12:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



ну, вы полезли уже глубоко. 
вот сама функция
Код

DWORD rGetValueSz(HKEY hReg, const wchar_t *name, wchar_t *&Data)
{
    DWORD i, Len=0;
    i=RegQueryValueExW(hReg, name, 0, NULL, NULL, &Len);
    if (i==ERROR_SUCCESS)
    {
        int l=Len / sizeof(wchar_t);
        Data=new wchar_t[l];
        i=RegQueryValueExW(hReg, name, 0, NULL, (PBYTE)Data, &Len);
        if (i==ERROR_SUCCESS)
        {
            return l;
        }
        else return 0;
    }
    else return 0;
};


PM MAIL   Вверх
artsb
Дата 15.1.2010, 12:36 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

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



Цитата(CTapMex @  15.1.2010,  12:29 Найти цитируемый пост)
ну, вы полезли уже глубоко. 

Тем не менее в тему.


Цитата(CTapMex @  15.1.2010,  12:29 Найти цитируемый пост)
wchar_t *&Data

амперсанд здесь не нужен.

И вы нигде не освобождаете Data.

Добавлено @ 12:39
Пробуйте так:
Код

wchar_t *rGetValueSz(HKEY hReg, const wchar_t *name, DWORD &res)
{
    wchar_t *Data;
    DWORD i, Len=0;
    res = 0;
    i=RegQueryValueExW(hReg, name, 0, NULL, NULL, &Len);
    if (i==ERROR_SUCCESS)
    {
        int l=Len / sizeof(wchar_t);
        Data=new wchar_t[l];
        i=RegQueryValueExW(hReg, name, 0, NULL, (PBYTE)Data, &Len);
        if (i==ERROR_SUCCESS)
        {
            res = l;
            return Data;
        }
        else {
            delete [] Data;
            return NULL;
        }
    }
    else return NULL;
};


Добавлено @ 12:41
А юзать так:
Код

wchar_t *Name = null;

DWORD len;
Name = rGetValue(hPluginRegistry, 'name', &len);
if (len<=1)  
  Name = L"default"; // но тогда эта строка - бред ИМХО

if(Name)
 delete[] Name;


Это сообщение отредактировал(а) artsb - 15.1.2010, 13:07


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
CTapMex
Дата 15.1.2010, 13:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(artsb @ 15.1.2010,  14:36)

амперсанд здесь не нужен.
И вы нигде не освобождаете Data.

 вот про удаление - да, не заметил. спасибо. 

Цитата(artsb @ 15.1.2010,  14:36)

Пробуйте так:

А юзать так:
Код

wchar_t *Name = null;

DWORD len;
Name = rGetValue(hPluginRegistry, 'name', &len);
if (len<=1)  
  Name = L"default"; // но тогда эта строка - бред ИМХО

delete[] Name;

да, так лучше будет . спасибо 
а про бред - твой самый первый вариант решения тут подойдет

Это сообщение отредактировал(а) CTapMex - 15.1.2010, 15:20
PM MAIL   Вверх
artsb
Дата 15.1.2010, 13:48 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

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



Если вы проверяете удалось ли что-то получить после вызова rGetValue, то лучше так:
Код

wchar_t *Name = null;
DWORD len;
Name = rGetValue(hPluginRegistry, 'name', &len);
if (!Name) {
  Name = new wchar_t[wcslen(L"default")];
  wcscpy(Name, L"default");
}
// ...
if(Name)
 delete[] Name;

а от len можно вообще избавиться.


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
CTapMex
Дата 15.1.2010, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



еще раз спасибо 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

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

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


 




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


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

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