• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Po dołączeniu bibliotek do .exe Program przestaje działać [C++ BUILDER 6]

0 głosów
457 wizyt
pytanie zadane 22 sierpnia 2018 w C i C++ przez Eragoh Nowicjusz (160 p.)

Witam, korzystam z C++ BUILDER 6, wszystko działa sprawnie w programie do momentu dołączenia do .exe bibliotek (odznaczam Use Dynamic RTL oraz Build with runtime packages). Wtedy przy próbie kompilacji program wysypuje błąd: "Access Violation at address 004AFF39. Read of Address 00000000.". Po czym podświetla się linijka   : ios_base(), w nowo otwartej karcie _ios.c. Błąd może mieć jakiś związek z biblioteką fsteam.h, ale nie mam pojęcia czy i dlaczego. Dołączam kod, jeśli okaże się potrzebny.

//---------------------------------------------------------------------------

#include <vcl.h>
#include <fstream.h>
#include <windows.h>

#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "trayicon"
#pragma resource "*.dfm"
TForm1 *Form1;
int s,wczesniej;
fstream plik;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------



void Koniec(int sekundy)
{
        plik.open("TIME.txt",ios::out);
        plik.clear();
        plik<<sekundy;

        plik.close();
        Application->Terminate();
}
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
        
        AnsiString godz,min,sec;
        s++;
        int godzin,minut,sekund;
        godzin=s/3600;
        minut=(s-godzin*3600)/60;
        sekund=s-godzin*3600-minut*60;

        godz=IntToStr(godzin);
        min=IntToStr(minut);
        sec=IntToStr(sekund);

        if(godzin<10) godz="0"+godz;
        if(minut<10) min="0"+min;
        if(sekund<10) sec="0"+sec;

        Label1->Caption = godz+":"+min+":"+sec;


        int godzindzis,minutdzis,sekunddzis;
        AnsiString godzdzis,mindzis,secdzis;
        int dzis=s-wczesniej;
        godzindzis=dzis/3600;
        minutdzis=(dzis-godzindzis*3600)/60;
        sekunddzis=dzis-godzindzis*3600-minutdzis*60;

        godzdzis=IntToStr(godzindzis);
        mindzis=IntToStr(minutdzis);
        secdzis=IntToStr(sekunddzis);

        if(godzindzis<10) godzdzis="0"+godzdzis;
        if(minutdzis<10) mindzis="0"+mindzis;
        if(sekunddzis<10) secdzis="0"+secdzis;

        Label2->Caption = "Czas Dzisiaj: "+godzdzis+":"+mindzis+":"+secdzis;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
        string linia;
        plik.open("TIME.txt",ios::in);
        if ( plik.peek() == std::ifstream::traits_type::eof() )
        s=0;
        else
        plik>>s;
        wczesniej=s;
        plik.close();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
        Koniec(s);
}
//---------------------------------------------------------------------------



void __fastcall TForm1::Zakocz1Click(TObject *Sender)
{
        Koniec(s);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ResetujCzas1Click(TObject *Sender)
{
        if(Application->MessageBox("Czy na pewno chcesz zresetować czas? \n Jego aktualna wartość przepadnie!"
        ,"ARE YOU SURE?!",MB_YESNO | MB_ICONWARNING | MB_TOPMOST)==6)
        {
                remove("TIME.txt");
                s=0;
                Application->Terminate();
        }
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Zmiedatstartow1Click(TObject *Sender)
{
        Form2->ShowModal();

}
//---------------------------------------------------------------------------

void __fastcall TForm1::TrayIcon1Restore(TObject *Sender)
{
        if(Form1->Visible==false)
                Form1->Show();
        else
                Form1->Hide();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Poka1Click(TObject *Sender)
{
        if(Form1->Visible==false)
                Form1->Show();
        else
                Form1->Hide();
}
//---------------------------------------------------------------------------

~~~~~~~~~~
ORAZ UNIT2:
~~~~~~~~~~

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------


void __fastcall TForm2::Button1Click(TObject *Sender)
{
        AnsiString data=Edit1->Text;
        Form1->Caption="Czas na komputerze od "+data;
        Close();

}
//------

 

komentarz 22 sierpnia 2018 przez j23 Mędrzec (195,220 p.)

Kilka uwag:

  • jest jakiś racjonalny powód, dla którego strumień plik jest globalny?
  • Nie używaj globalnego wskaźnika Form1 we wnętrzu metod klasy TForm1, chyba że wiesz, co robisz (w co wątpię).
  • linia 40: zakładanie, że timer okienkowy będzie wywoływał Timer1Timer dokładnie co sekundę jest naiwnością. Po godzinie może się okazać, że twój program naliczył nie 60 a np. 40 minut. Tak zrób:
    	time_t start_time = clock(); // gdzieś, gdzie startujesz timer
    	...
    
    	/* w TForm1::Timer1Timer */
    	int diff_time = (clock() - start_time) / CLOCKS_PER_SEC;
    
    	std::ostringstream oss;
    	oss.fill('0');
    
    	div_t d = div(diff_time, 3600);
    	oss << std::setw(2) << d.quot << ':';
    	d = div(d.rem, 60);
    	oss << std::setw(2) << d.quot << ':' << std::setw(2) << d.rem << '\n';
        
    	Label1->Caption = oss.str().c_str();

     

komentarz 22 sierpnia 2018 przez Eragoh Nowicjusz (160 p.)

Bardzo dziękuje za pomoc, rozwiązaniem mojego problemu było tak jak zaznaczył Pan w punkcie 1., przeniesienie strumienia plik z globalnego do konkretnych funkcji.

Odnośnie punktu 2. sam nie tworzyłem tego wskaźnika, Builder robi go automatycznie, przy tworzeniu nowej aplikacji. Próbowałem go usunąć z kodu w różnych aplikacjach które już robiłem, w niektórych nie ma to wpływu na poprawność kompilacji, a w innych (tej również) wyrzuca błąd:

[Linker Error] Unresolved external '_Form1' referenced from D:\...\CZAS NA KOMPUTERZE\PROJECT1.OBJ

Zapewne gdzieś, nawet nieświadomie, poprzez Interfejs buildera go użyłem. Zostawiłem ten wskaźnik, bo bez niego jest błąd, a nie zauważyłem na ten moment żadnego jego negatywnego wpływu na program.

 

W punkcie 3. natomiast dziękuję za poradę, bo tak jak powiedział Pan wcześniej, na ten moment nie wiem co robię, nie spotkałem się wcześniej z div_t, lub oss.fill, także w tej chwili nie do końca ten kod rozumiem. Uzupełnię wiedzę, i do tego wrócę.

Jeszcze raz dziękuję za Pomoc wink

komentarz 22 sierpnia 2018 przez j23 Mędrzec (195,220 p.)

Próbowałem go usunąć z kodu

Nie możesz tego wskaźnika usunąć, bo, jak sam wspomniałeś, kompilator go tam z automatu wstawia, ma jakiś ku temu powód. Chodzi o to, że odwoływanie się do metod/pól klasy z wnętrza tejże poprzez globalny wskaźnik jest a) bezsensowne b) zaciemniające kod c) błędogenne.

komentarz 22 sierpnia 2018 przez Eragoh Nowicjusz (160 p.)

Dziękuję, zapamiętam laugh

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

0 głosów
1 odpowiedź 719 wizyt
+1 głos
3 odpowiedzi 2,291 wizyt

93,776 zapytań

142,736 odpowiedzi

323,388 komentarzy

63,381 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...