Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.09.2012, 02:38   #1
DIMMUA
Пользователь
 
Регистрация: 06.07.2012
Сообщений: 13
По умолчанию Глобальная переменная сама обнуляется

Ув. форумчане, хочу вас спросить, т.к. опыта у самого мало (да вообще, самоучка). Только недавно узнал, что использование глобальных переменных это плохо и нужно по возможности описывать их локально, или, если надо, в каждой процедуре описывать.

У меня программа, несколько форм, на Form1, в разделе var "igraet: Byte;". Дальше в этой форме я активно работаю с этой переменной (значение она принимает от 0 до 4). И потом, ну, скажем, по таймеру на Form6 срабатывает другая процедура, которой нужно знать значение этой переменной... и вот тут проблема, как оказалась, примерно 1 раз из 20-30 переменная передается уже "0". Т.е. на форме1, после всех манипуляций я пишу:
Код:
Memo1.Lines.Add(IntToStr(igraet)) - выводит 4, как и должно быть;
Form1.Timer1.Enabled:=True;
в обработчике таймера (интервал таймера короткий, если это важно 100-400 мс) стоим только "Form1.ProcZakaz;" И вот, в первой строчек этой ProcZakaz я пишу:
Код:
Memo1.Lines.Add(IntToStr(igraet)) - но получаю уже 0!;
Мне бы хотелось узнать, вообще, возможно ли такое? Переменная точно становиться 0, но хочу узнать, если грешить на Дельфи, то как защититься, а если это не Дельфи, то как такое происходит?
DIMMUA вне форума Ответить с цитированием
Старый 14.09.2012, 04:06   #2
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

В этом и трабл глоб. переменных. Их нельзя контролировать.
Работают по принципу "Кто успел, тот и съел".
Человек_Борща вне форума Ответить с цитированием
Старый 14.09.2012, 08:10   #3
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Только недавно узнал, что использование глобальных переменных это плохо и нужно по возможности описывать их локально, или, если надо, в каждой процедуре описывать.
Вот так вот программисты и портятся...
Цитата:
Переменная точно становиться 0
Так ты выясни прежде всего где ей присваивается что-то.
И вообще зачем ты обращаешся к ней из другой формы.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 14.09.2012, 08:21   #4
astecenko
Homo Interneticus
Форумчанин
 
Аватар для astecenko
 
Регистрация: 04.03.2011
Сообщений: 611
По умолчанию

DIMMUA прочтите статью GunSmoker-а Что плохого в глобальных переменных?
astecenko вне форума Ответить с цитированием
Старый 14.09.2012, 10:33   #5
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Ну собственно говоря не такая уже она и глобальная. Это переменная формы, а форм у него несколько.
Цитата:
DIMMUA прочтите статью GunSmoker-а Что плохого в глобальных переменных?
Он уже написал, что понял свои ошибки. Теперь их нужно отследить и исправить.

ТС, попробуй проставить бреакпоинты на те места, где твоя переменная приравнивается к нулю и прогони несколько раз свою прогу до наступления твоего случая.
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 14.09.2012, 11:37   #6
astecenko
Homo Interneticus
Форумчанин
 
Аватар для astecenko
 
Регистрация: 04.03.2011
Сообщений: 611
По умолчанию

Utkin, не судите о содержании по названию. В статье Александр предлагает несколько вариантов решения и избегания потенциальных проблем с глобальными переменными. Возможно ТС выберет какой-то вариант. Как уже писал Stilet, не стоит портить программиста с профессионального "младенчества".
astecenko вне форума Ответить с цитированием
Старый 14.09.2012, 14:44   #7
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Цитата:
Сообщение от astecenko Посмотреть сообщение
Utkin, не судите о содержании по названию. В статье Александр предлагает несколько вариантов решения и избегания потенциальных проблем с глобальными переменными. Возможно ТС выберет какой-то вариант. Как уже писал Stilet, не стоит портить программиста с профессионального "младенчества".
Я прочитал статью прежде чем написал свой пост.
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 14.09.2012, 14:56   #8
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

DIMMUA, покажи немного кода. Не очень понятно, переменная у тебя или поле объекта.

Если это глобальная переменная, то быстро отследить проблему можно так:
1. Переименуй её (чтобы компилятор поймал все обращения к ней).
2. Введи функцию GetIsPlaying и процедуру SetIsPlaying. Понятно, что они должны делать?
3. Все обращения к переменной, которые тебе укажет компилятор (из-за п.1), замени или на GetIsPlaying или на SetIsPlaying.
4. Установи точку останова внутри SetIsPlaying.
5. Запусти программу и следи, кто вызывает SetIsPlaying.

Это как быстрый фикс. Ну а вообще можно подумать насчёт улучшения кода.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 15.09.2012, 00:49   #9
DIMMUA
Пользователь
 
Регистрация: 06.07.2012
Сообщений: 13
По умолчанию

Спасибо всем за советы!
Буду сейчас следовать всеми приведенными советами. Я понял, что глобальные переменные "Кто успел, тот и съел". Я вот что хочу узнать - "Может ли Windows испортить мою переменную от того что она глобальная, а не локальная?" и, кстати, после прочтения статьи GunSmoker-а "Что плохого в глобальных переменных?" я решил создать тему, т.к. моих знаний хватило, чтобы поверхностно понять о чем речь.

Вот немножко кода, не знаю, поможет ли он вам:

Переменная играет, прнимает разные значение в зависимости от:
0 - ничего не играет
1 – играет музыкальный фон
2 – играет заказанная музыка
4 – играет заказанная клип

Код:
unit MusicProg;
interface
uses
  Kol, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ComObj, ActiveX, ExtCtrls, ShellAPI, idGlobal,
  CRC32, iniFiles, mmSystem, Math, ALProgressBar, Jpeg;
type
  TForm1 = class(TForm)
  private
    procedure ProcPlay(z: string);
    procedure ProcPlayFon(z: string);
    procedure Start;
    procedure ZakazLabel(z: string);
    procedure ProcOrder;
     { Private declarations }
  public
    procedure ProcCredit;
    { Public declarations }
  end;
var
  Form1: TForm1;
 igraet: Byte;
  implementation
uses Unit2, Unit3, Unit4, Unit5, Unit6, Unit7, Unit8, Unit9;
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
igraet:=0;
end;

procedure TForm1.Start;
begin
  Memo1.Lines.Add('Заказ = '+z);
  Memo1.Lines.Add('igraet было '= ' + IntToStr(igraet)); //было 0 или  1
Определяем расширение файла из переменной z (string)  и в зависимости от того, музыка или видео это, присеваем 2 или 4.
Memo1.Lines.Add('igraet стало '= ' + IntToStr(igraet)); //стало 2 или 4
Form6.WMP.URL := z; (компонент ActiveX, Windows Media Player)
Form6.WMP.controls.play; // отсылаем на воспроизведение
end;

Мигрируем на Form6
procedure TForm6.WMPPlayStateChange(ASender: TObject; NewState: Integer);
begin
  if (NewState = 3) then // если WMP играет, то…
  begin
    Form1.Timer1.Enabled := True; // запускаем Таймер, который будет двигать прогресс бар воспроизведения, интервал 1 с
    dlina := Trunc(Form6.WMP.currentMedia.duration);
    Form1.Memo1.Lines.Add('Длина = ' + IntToStr(dlina));
    Form1.Memo1.Lines.Add(Играет на Форме 6 ' + IntToStr(igraet)); // иногда, непонятно как и закономерность становиться 0
    if igraet = 4 then
      Form6.Show;
  end;

Вернемся на Forn1
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if Form6.WMP.playState = 3 then
  begin
    if igraet = 2 then
      ProgressBar1.Position := Trunc(Form6.WMP.controls.currentPosition);
  end
  else
  begin
    if igraet = 4 then
      Form6.Hide;
    Form1.Timer1.Enabled := False;
    ProgressBar1.Position := 0;
    igraet := 0;
  end;
end;
DIMMUA вне форума Ответить с цитированием
Старый 15.09.2012, 06:09   #10
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
"Может ли Windows испортить мою переменную от того что она глобальная, а не локальная?"
нет, портит её ваша же программа.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Глобальная переменная winhttp C# (си шарп) 15 20.07.2016 16:03
Обнуляется переменная Leonid183 Visual C++ 0 27.10.2011 16:06
Глобальная переменная mutabor JavaScript, Ajax 2 31.12.2010 12:23
Обнуляется переменная Hippie Помощь студентам 1 09.01.2010 20:22
C++ [Глобальная переменная] Lemo Помощь студентам 2 26.10.2009 17:49