Access Violation tylko przy kompilacji

Odpowiedz Nowy wątek
2011-08-10 20:24
0

Sytuacja wygląda tak:
piszę program okienkowy w C++ Builder, w którym używam zapisu/odczytu plików przez fstream. Wszystko było ok do pewnego momentu, kiedy to podczas zapisu i odczytu zaczął wyskakiwać:

Access violation at address 00406E13 in module 'Project1.exe'. Read of address 00000004.

O dziwo tak się dzieje tylko wtedy, jak kompiluję i uruchamiam program (F9). Gdy najpierw kliknę na "Build Project1" i dopiero wtedy F9 to wszystko jest OK (normalnie zapisuje/odczytuje pliki bez błędów) do czasu zmiany w kodzie.

O co może chodzić? Na początku podejrzewałem wychodzenie poza zakres zmiennych, ale jakoś wszystko działa normalnie gdy najpierw zbuduję projekt.

C++ builder jeszcze żyje? Chciałem się ogarnąć jak u nich wygląda wsparcie standardów, szczególnie C++0x, ale odpowiednia podstrona Embercardo przywitała mnie zachęcającym komunikatem "Database Error: Unable to connect to the database:Could not connect to MySQL" - Zjarek 2011-08-10 20:43
W szkole miałem Dev C++ ale po interwencji u nauczyciela pozwolił mi zainstalować... BCB właśnie :D. Z dwojga złego wybrałem trzecią możliwość i do teraz używam GCC z konsoli ;) - msm 2011-08-10 21:54
Po kłopotach z MySQLem doszedłem do wniosku, że jedynym sensownym środowiskiem pod windowsem jest VS. DevC++ miał świetny pomysł z menedżerem pakietów, szkoda, że nikt tego pomysłu nie kontynuował (pomijając Cygwina, ale to trochę inna bajka). Instalacja bibliotek pod MinGW to koszmar (w porównaniu z np. apt-getem). Do tego linia komend w windowsie to porażka (przyznam się, nie korzystałem jeszcze z PowerShella). Nie ma nawet ls oraz rm (wpisuje automatycznie i zawszę dostaje błedy). - Zjarek 2011-08-10 22:08
dlaczego miałoby być ls i rm, skoro jest dir i del? - Azarien 2011-08-10 22:24

Pozostało 580 znaków

2011-08-10 20:36
0

Pokaż kod. Ja miałem kiedyś inaczej -> w środowisku było ok, za kilka robiłem porządki i wcieło mi gdzieś pliki źródłowe, a został sam exe. Uruchamiam sobie, a tu Access Violation :(


<error>There was an error during loading user signature. Please try to reboot the Universe and check again.</error>

Pozostało 580 znaków

2011-08-10 20:56
0

Skupcie się na wywołaniu procedury dla Button2 - to ta procedura może sprawiać problemy.
Błąd Access Violation pojawia mi się w linijce: ofstream plik(temp);

//---------------------------------------------------------------------------
 
#include <vcl.h>
#include <windows.h>
#include <string>
#include <sstream>
#include <fstream.h>
#pragma hdrstop
 
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "pies"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
 
//jeśli wyrazy są takie same, zwraca TRUE, w przeciwnim wypadku FALSE:
bool takie_same(char arg1[50], char arg2[50])
{
        if(strcmp(arg1, arg2)==0) return true;
        else return false;
}
 
//wyprowadza nazwę programy w danym podkluczu
String wartosc_wyswietlana(char sciezka[MAX_PATH], HKEY klucz, DWORD typ_danych, DWORD rozmiar)
{
        CHAR wartosc[128];
        RegOpenKeyEx(HKEY_LOCAL_MACHINE,sciezka,0,KEY_READ,&klucz);
        RegQueryValueEx(klucz,"DisplayName",0,&typ_danych,(LPBYTE)wartosc,&rozmiar);
        return wartosc;
}
 
//jeśli folder istnieje, zwraca TRUE, w przeciwnim wypadku FALSE:
bool folder_istnieje(string file)
{
        DWORD returnvalue;
        returnvalue = GetFileAttributes(file.c_str());
        if(returnvalue == ((DWORD)-1)) return false;
        else return true;
}
 
//jako argumenty podaje się składowe: R, B, B
int kolor(int R, int G, int B)
{
        return B * 65536 + G * 256 + R;
}
 
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 
}
//---------------------------------------------------------------------------
 
//PRZYCISK ODPOWIADAJĄCY ZA ZAPIS DO PLIKU:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
     String x;
 
     if(SaveDialog1->Execute())
     {
        strcpy(temp, SaveDialog1->FileName.c_str());
        strcat(temp, ".txt");
        ofstream plik(temp);
        if(plik)
        {
            plik<<"[lista_zainstalowanych_programów]\n";
            plik<<indeks<<endl;
            for(i=0; i<indeks ;i++)
                    plik<<tablica[i]<<"\n";
 
            plik.close();
            String x;
            x="Lista zainstalowanych programów zapisana w ";
            x+=temp;
            MessageBox(NULL, x.c_str(), "Gotowe", MB_ICONINFORMATION);
        }
        else MessageBox(NULL, "Nie można dokonać zapisu", "Problem", MB_ICONERROR);
     }
}
//---------------------------------------------------------------------------
//(funkcja pobierająca dane - nie wrzuciłem bo za długie. Poza tym nie sprawia problemów.)
//---------------------------------------------------------------------------
 
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
//przy zamykaniu programu, usuwane są komponenty stworzone dynamicznie
 
    //zmienna liczba_podkluczy jest ustalona, więc to nie przez to
    for (i=0; i<liczba_podkluczy; i++)
    {
       delete tablica[i];
       delete tablica_plik[i];
    }
    delete [] tablica;
    delete [] tablica_plik;
 
    delete [] wpisy_zrodlo;
    delete [] brakujace;
}
//---------------------------------------------------------------------------

Unit1.h:

//---------------------------------------------------------------------------
 
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
#include <Dialogs.hpp>
#include <TabNotBk.hpp>
#include <ExtCtrls.hpp>
#include <jpeg.hpp>
#include <FileCtrl.hpp>
#include "pies.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
        TTabbedNotebook *TabbedNotebook1;
        TLabel *Label1;
        TLabel *Label2;
        TLabel *Label3;
        TLabel *Label4;
        TRichEdit *RichEdit1;
        TButton *Button2;
        TSaveDialog *SaveDialog1;
        TOpenDialog *OpenDialog1;
        TImage *Image1;
        TLabel *Label5;
        TLabel *Label6;
        TEdit *Edit1;
        TButton *Button4;
        TButton *Button5;
        TButton *Button6;
        TButton *Button7;
        TRichEdit *RichEdit2;
        TButton *Button8;
        TLabel *Label7;
        TImage *Image2;
        TButton *Button9;
        TScrollBox *ScrollBox1;
        TImage *Image3;
 
        void __fastcall Button2Click(TObject *Sender);
        void __fastcall Button8Click(TObject *Sender);
        void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
private:
 
public:
        DWORD liczba_podkluczy;
        unsigned int i, j, k, m, indeks, licznik, il_linijek, il_wpisow_zainst;
        char temp[100];
        string s, plik_desktop, nl;
 
        //char tablica[300][100], tablica_plik[300][100];
        char **tablica, **tablica_plik;
        int *brakujace;
        string *wpisy_zrodlo;
 
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
edytowany 3x, ostatnio: Nezetus, 2011-08-10 21:07

Pozostało 580 znaków

2011-08-10 21:12

Daleki strzał (po przebrnięciu przez "o k... co za kod i czy on wie, że można zmieniać nazwy elementów GUI"), może to być spowodowane tym, że program kompilowany i uruchamiany jest w innym katalogu, niż program budowany oraz, że nazwa tego katalogu z nazwą pliku jest większa niż 100 znaków, przez co następuje przepełnienie tablicy temp.

Problem rozwiązany. Wystarczyło zapisać wszystkie pliki projektu w nowym folderze. "(po przebrnięciu przez "o k... co za kod i czy on wie, że można zmieniać nazwy elementów GUI")" - Chodziło ci o długość kodu czy styl pisania? :P Poza tym wiem, że można zmieniać nazwy elementów GUI, ale tego nie robiłem, bo robię prosty program i nie opłaca mi się specjalnie zmieniać nazw kilku komponentów. - Nezetus 2011-08-10 21:28
Masz 9 buttonów, 6 labelów i sporo innych rzeczy, ze swojego doświadczenia wiem, że nadawanie nazw komponentom nie jest czasem zmarnowanym. Co do stylu pisania, to szczególnie mi się nie podoba mieszanie std::stringów z cstringami i Strringami, zmienna temp w klasie (WTF?), stosowanie tylu wskaźników w C++ (std::vector z włączonymi optymalizacjami naprawdę nie jest zauważalnie wolniejszy, dodatkowo jestem zatwardziałym zwolennikiem RAII). - Zjarek 2011-08-10 21:33

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0