Avatar billede waldeinburg Nybegynder
31. oktober 2001 - 19:14 Der er 51 kommentarer og
1 løsning

flere members= ulovlig handling, hvorfor dog?

Jeg er igang med at lave et Windows-program i C++, og jeg har et meget mærkeligt problem, som blokere min videre udvikling af programmet en hel del: Jeg kan ikke oprette members, uden at mit program udfører en ulovlig handling eller i det hele taget opfører sig underligt. Jeg tror ikke det kan være hukommelsesproblemer, for programmet er overhovedet ikke stort endnu. Der skal ikke mere end en bette char til. Det virker fint, hvis jeg gør samme variabel global i stedet for.
Er der nogen, der kan hjælpe mig, for det driver mig til vanvid!!!
Avatar billede mickni33 Nybegynder
31. oktober 2001 - 21:07 #1
Er det noget du kan vise med lidt kode ?
Avatar billede jpk Nybegynder
31. oktober 2001 - 22:37 #2
Er det eneste du gør, at tilføje variablen som en member, altså UDEN at bruge den?
Hvis ja, så prøv at slette alle kompilergenererede filer og genbyg skidtet...
Avatar billede disky Nybegynder
01. november 2001 - 08:46 #3
Noget kode tak.
Avatar billede waldeinburg Nybegynder
01. november 2001 - 09:44 #4
Det virkede desværre ikke, jpk. Noget kode? Mmh, det kunne godt gå hen og blive stort, men jeg kan lige vise princippet i det:
class Klasse
{
...
};
virker
men så:
class Klasse
{
...
private:
  int _i;
};
og så virker det lige pludselig ikke mere.
Det var nok ikke til meget hjælp. I skriver bare igen, hvis I vil have noget rigtigt kode, så kan jeg evt. maile det.
Avatar billede disky Nybegynder
01. november 2001 - 09:45 #5
Hvordan instantierer du den klasse ?
Avatar billede jpk Nybegynder
01. november 2001 - 09:46 #6
Hvilket udviklingsmiljø/compiler bruger du?
Avatar billede waldeinburg Nybegynder
01. november 2001 - 10:33 #7
til disky:
hvordan jeg instatierer den? øh...
Klasse nyKlasse;
...hvad ellers. Men det er altså kun et eksempel. Jeg tror hellere, jeg må sende koden. Kan I ikke give mig jeres email-adresser.

til jpk:
Jeg bruger Borlands gratis compiler (jeg HAR installeret de nyeste patches) og programmerings-teksteditoren ConTEXT (men editoren skulle vel ikke kunne gøre en forskel)
Avatar billede disky Nybegynder
01. november 2001 - 10:34 #8
Hvordan bruger du din klasse ?

når du f.eks. skriver:

Klasse k=new Klasse();

Instantierer du et objekt af typen Klasse.
Avatar billede soepro Nybegynder
01. november 2001 - 10:46 #9
Dette her virker - og viser princippet:

#include <iostream.h>
#include <string.h>

class shared
{
  public:
  shared(int x)    { data = x; };
  shared(void)    { data = 0; };
  void Mx(int add) { data += add; };
  protected:
  int  data;
};
class inheritA : shared
{
  public:
  inheritA(int x) : shared(x) { strcpy(name, \"[Unknown]\"); };
  inheritA(char *n, int x) : shared(x) { strcpy(name, n); };
  int M2(int add)            { Mx(add); return data; };
  int M1(int add)            { data = 0; return M2(add); };
  protected:
  char name[20];
};
class inheritB : shared
{
  public:
  inheritB(int x) : shared(x) { /* No extra */; };
  int M4(int add)            { Mx(add); return data; };
  int M3(int add)            { data = 0; return M4(add); };
};

int main (void)
{
  cout << \"S† k›rer vi igen ...\" << endl;

  inheritA A(\"Ford\", 3);
  cout << \"V‘rdien er: \"<< A.M2(4) << endl;  // Skal vise 7 = 3 (fra init) + 4 herfra.
  cout << \"V‘rdien er: \"<< A.M1(13) << endl; // Skal vise 13 = 13 herfra, da M1 nulstiller inden kald.

  inheritB B(2);
  cout << \"V‘rdien er: \"<< B.M4(9) << endl;  // Skal vise 11 = 2 (fra init) + 9 herfra.
  cout << \"V‘rdien er: \"<< B.M3(39) << endl; // Skal vise 39 = 39 herfra, da M1 nulstiller inden kald.

  return 0;
}

Det kører under TC++ 3.0, så MVC og BCB kan begge \"klare\" det også.
Avatar billede waldeinburg Nybegynder
01. november 2001 - 10:53 #10
jeg kan ikke umiddelbart se, hvordan din kode skulle hjælpe mig til at forstå problemet. Jeg kører selvfølgelig også efter de almindelig principper (det kan vel ikke gøres anderledes), men sagen er den i dette tilfælde, at det opfører sig ekstremt underligt.
Avatar billede soepro Nybegynder
01. november 2001 - 10:59 #11
Så må du s.. være mere specifik. Du lægger en lille stump ud, som ingen af os kan finde noget galt i... ALTSÅ må det være noget andet i din kode. Eksempler som d.o. er tænkt som hjælp til dig til msåke selv at opdage hvad der er galt.

Du skriver bare at \'og så virker det lige pludselig ikke mere\' - det er dælme godt nok ikke en særlig præcis angivelse af dit problem.

Husk: Som man spørger, således for man svar !

(Ikke noget jeg har fundet på, men vist sagt af Søren Kierkegaard.)
Avatar billede soepro Nybegynder
01. november 2001 - 11:00 #12
Post koden her vha. Copy-Paste, så kan vi alle kigge på det.
Avatar billede waldeinburg Nybegynder
01. november 2001 - 11:08 #13
ok. men det er altså en hel del
Avatar billede waldeinburg Nybegynder
01. november 2001 - 11:57 #14
undskyld forsinkelsen, men nettet gik lige ned.
her er noget af den (der er altså en hulens masse, hvis jeg skal have det hele med, men I siger bare til, så kommer jeg også med den). I skal ikke tage jer af den udkommenterede kode. Det er bare fordi det stadig er på forsøgsplanet, og der er ting og sager som skal slås fra og sådan.

// %PARAMETERS = \"WinLib\"
#ifndef __WINLIB__FORM_H
#define __WINLIB__FORM_H

#include \"Base.h\"
#include \"Controller.h\"

#pragma warn -8026 // Functions with exception specifications are not expanded inline

namespace Win
{
  class Form
  {
    protected:
      explicit Form (Class & pClass)
        : _windowMaker (pClass)
      {}

      Form (char const * className, HINSTANCE hInst)
        : _windowMaker (className, hInst)
      {}

    public:
      std::pair <BOOL, BOOL> Display (int cmdShow) const
      {
        return _parentWindow.Display (cmdShow);
      }

    protected:
      Dow _parentWindow;
      DowMaker _windowMaker;
  };


  class Control
  {
    protected:
      Control (
        DowMaker & windowMaker,
        Controller & controller,
        char * text,
        int x, int y, int width, int height,
        char * type
      )
        : _windowMaker (windowMaker),
        _controller (controller),
        _text (text),
        //_x (x), _y (y), _width (width), _height (height),
        _type (type)
      {}

      void SetParams (HWND parent)
      {
        _windowMaker.SetDefaults ();
        _windowMaker.SetPos (100, 100);//_x, _y);
        _windowMaker.SetDims (100, 100);//_width, _height);
        _windowMaker.SetStyle (WS_CHILD);
        _windowMaker.SetParent (parent);
        _windowMaker.SetClassName (_type);
      }

      void CreateControl ()
      {
        _control = _windowMaker.Create (_controller, _text);
        _control.SetLong <Controller *> (& _controller);
        _controller.SetWindowHandle (_control);
      }
    public:
      virtual void Create (HWND parent)
      {
        SetParams (parent);
        CreateControl ();
      }

      std::pair <BOOL, BOOL> Display (int cmdShow = SW_SHOW) const
      {
        return _control.Display (cmdShow);
      }
    public:
      char * _text, * _type;
      //int _x, _y, _width, _height;
      Dow _control;
      DowMaker & _windowMaker;
      Controller & _controller;
  };


  //===============================================

  class ButtonController : public Controller
  {
    public:
      virtual bool OnClick () { return false; }
  };

  class Button : public Control
  {
    public:
      Button (
        DowMaker & windowMaker,
        ButtonController & controller,
        char * text,
        int x, int y, int width, int height
      )
        : Control (
          windowMaker,
          controller,
          text,
          x, y, width, height,
          \"BUTTON\"
        )
      {}
  };

}


#pragma warn +8026 // Functions with exception specifications are not expanded inline

#endif


// %PARAMETERS = \"winlibtest\"
#ifndef TESTFORM_H
#define TESTFORM_H

#include \"winlib\\form.h\"

class CtrlController : public Win::ButtonController
{
  public:
    bool OnClick ()
    {
      char buf [256];
      wsprintf (buf, \"%X\", static_cast <HWND> (_window));
      MessageBox (_window, buf, \"\", MB_OK);
      ::MessageBox (_window, \"det går jo fint\", \"jamen...(!)\", MB_OK);
      return true;
    }
};

class TestForm : public Win::Form
{
  public:
    TestForm (Win::Class & pClass)
      : Win::Form (pClass),
      _control1 (_windowMaker, _ctrlController, \"En control\", 50, 50, 200, 50)
    {}

    void Create ()
    {
      _parentWindow = _windowMaker.Create (_ctrlController, \"TestForm\");
      _control1.Create (_parentWindow);
      _control1.Display ();
    }

  private:
    CtrlController _ctrlController;
    Win::Button _control1;
    // OG HVIS JEG SÅ F.EKS. SKRIVER int _i; HER GÅR SKIDTET NED
};

#endif

// %PARAMETERS=\"winlibtest\"

//#include \"winlib\\base.h\"
//#include \"controller.h\"
#include \"testform.h\"


int WINAPI WinMain
  (HINSTANCE hInst, HINSTANCE, LPSTR, int cmdShow)
{
  try
  {
    Win::Class mainClass (\"mainClass\", hInst);
    //Direct::SetWinClassParams (mainClass);
    mainClass.Register ();

    TestForm form (mainClass);
    form.Create ();
    form.Display (cmdShow);
    /*
    Win::DowMaker winMaker (mainClass);
    //Direct::SetWinDowMakerParams (winMaker);
    Win::Dow window;
    TopController ctrl;
    window = winMaker.Create (ctrl, \"New Window\");
    window.Display (SW_SHOWNORMAL);
    */
    MSG  msg;
    BOOL status;

    while ((status = ::GetMessage (& msg, 0, 0, 0)) != 0)
    {
      if (status == -1)
        return -1;
      ::TranslateMessage (& msg);
      ::DispatchMessage (& msg);
    }
    return msg.wParam;
  }
  catch (Win::Exception e)
  {
    e.Display ();
  }
  catch (char * estr)
  {
    Win::Exception e (estr);
    e.Display ();
  }
  catch (...)
  {
    Win::Exception e (\"Unknown error. Possibly this:\", ::GetLastError ());
    e.Display ();
  }
  return -1;
}
Avatar billede waldeinburg Nybegynder
01. november 2001 - 12:00 #15
jeg beklager meget, at jeg ikke er mere specifik med mit problem, men det jeg ved altså ikke hvad jeg skal trække ud, når jeg ikke kan forklare hvorfor det går ned.
respekt til Søren Kirkegaard :)
Avatar billede waldeinburg Nybegynder
01. november 2001 - 12:03 #16
forresten: den udkommenterede linje i objektet control (//int _x, _y, _width, _height;) er også en linje, som får skidtet til at gå ned. Her får jeg et NULL fra CreateWindowEx (hvis ikke jeg får en ulovlig handling), men GetLastError () viser ikke nogen fejl.
Dow og DowMaker er inkapslinger af CreateWindowEx og HWND.
Avatar billede disky Nybegynder
01. november 2001 - 12:13 #17
det var dog en mystisk måde at navngive variabler på
Avatar billede waldeinburg Nybegynder
01. november 2001 - 12:42 #18
Dow og DowMaker? Det er fordi de ligger under et namespace, der hedder Win. Altså hedder de Win::Dow (window) og Win::DowMaker (window maker)
Avatar billede waldeinburg Nybegynder
01. november 2001 - 12:44 #19
hvis de er de der underscores før navnene, du mener, er det bare en måde, jeg navngiver private members på. Så kan man hurtigere skeldne fra andre variabler.
Avatar billede soepro Nybegynder
01. november 2001 - 15:12 #20
Og hvilken del af programmet er det så den kaster op over ?
Avatar billede waldeinburg Nybegynder
02. november 2001 - 09:43 #21
nå, I får lige base.h

// %PARAMETERS = \"WinLib\"
#ifndef __WINLIB__BASE_H
#define __WINLIB__BASE_H


#include <windows.h>
#include <string>
#include <utility>
#include <cstring>

#include \"Exception.h\"
#include \"Procedure.h\"

namespace Win
{
  class Class;
  class DowMaker;
}

namespace Direct
{
  void SetWinClassParams (Win::Class & WinClass);
  void SetWinDowMakerParams (Win::DowMaker & WinDowMaker);
}

namespace Win
{
  class Class : protected WNDCLASSEX
  {
    friend void Direct::SetWinClassParams (Class & WinClass);
    friend class DowMaker;

    public:
      Class (char const * className, HINSTANCE hInst, WNDPROC WinProcedure = StdProcedure)
      {
        cbSize = sizeof (WNDCLASSEX);
        style = 0;
        lpfnWndProc = WinProcedure;      // window procedure: mandatory
        cbClsExtra = 0;
        cbWndExtra = 0;
        hInstance = hInst;              // owner of the class: mandatory
        hIcon = NULL;
        hCursor = ::LoadCursor (0, IDC_ARROW);
        hbrBackground = reinterpret_cast <HBRUSH> (COLOR_WINDOW + 1);
        lpszMenuName = NULL;
        lpszClassName = className; // mandatory
        hIconSm = NULL;
      }

      void Register ()
      {
        if (::RegisterClassEx (this) == 0)
          throw Exception (\"RegisterClassEx failed\");
      }
  };


  template <class T>
  inline T GetLong (HWND hwnd, int which = GWL_USERDATA)
  {
    return reinterpret_cast <T> (::GetWindowLong (hwnd, which));
  }

  template <class T>
  inline T SetLong (HWND hwnd, T value, int which = GWL_USERDATA)
  {
    return reinterpret_cast <T> (::SetWindowLong (hwnd, which, reinterpret_cast <long> (value)));
  }


  /*  We can\'t include Controller.h before declaration of Win::Dow because Win::Controller
      has a Win::Dow member, wich requires a implementation of Win::Dow before the implementation
      of Win::Controller. A reference requires declaration only. */
  class Controller;

  class Dow
  {
    public:
      Dow (HWND h) : _h (h) {}
      Dow () : _h (NULL) {}

      Dow & operator = (HWND h)
      {
        _h = h;
        return *this;
      }

      void SetHandle (HWND h) { _h = h; }

      operator HWND () { return _h; }

      template <class T>
      T GetLong (int which = GWL_USERDATA) const
      {
        return reinterpret_cast <T> (::GetWindowLong (_h, which));
      }

      template <class T>
      T SetLong (T value, int which = GWL_USERDATA) const
      {
        return reinterpret_cast <T> (::SetWindowLong (_h, which, reinterpret_cast <long> (value)));
      }

      std::pair <BOOL, BOOL> Display (int cmdShow) const
      {
        std::pair <BOOL, BOOL> retvalues;
        retvalues.first = ::ShowWindow (_h, cmdShow);
        retvalues.second = ::UpdateWindow (_h);
        return retvalues;
      }
    protected:
      HWND _h;
  };

  class DowMaker
  {
    friend void Direct::SetWinDowMakerParams (DowMaker & WinDowMaker);

    public:
      explicit DowMaker (Class & pClass)
        : _className (pClass.lpszClassName),
          _hInst (pClass.hInstance)
      {
        MessageBox (0, \"6\", \"\", MB_OK);
        SetDefaults ();
        MessageBox (0, \"7\", \"\", MB_OK);
      }

      DowMaker (char const * className, HINSTANCE hInst)
        : _className (className),
          _hInst (hInst)
      {
        SetDefaults ();
      }


      void SetDefaults ()
      {
        _exwStyle = 0;
        MessageBox (0, \"8\", \"\", MB_OK);
        std::strcpy (\"New window\", _windowName);
        MessageBox (0, \"9\", \"\", MB_OK);
        _wStyle = WS_OVERLAPPEDWINDOW;
        _x = CW_USEDEFAULT;
        _y = 0;
        _width = CW_USEDEFAULT;
        _height =0;
        _hWndParent = 0;
        _hMenu = NULL;
        _data = NULL;
      }

      void AddExStyle (DWORD style) { _exwStyle |= style; }
      void AddStyle (DWORD style) { _wStyle |= style; }

      void SetExStyle (DWORD style) { _exwStyle = style; }
      void SetClassName (char const * name) { _className = name; }
      void SetStyle (DWORD style) { _wStyle = style; }
      void SetPos (int x, int y)
      {
        _x = x;
        _y = y;
      }
      void SetXPos (int x) { _x = x; }
      void SetYPos (int y) { _y = y; }
      void SetDims (int width, int height)
      {
        _width = width;
        _height = height;
      }
      void SetWidth (int width) { _width = width; }
      void SetHeight (int height) { _height = height; }
      void SetParent (HWND parent) { _hWndParent = parent; }
      void SetMenu (HMENU menu) { _hMenu = menu; }


      HWND Create (Controller & ctrl, char const * title)
      {
        _windowName = title;
        _h = ::CreateWindowEx (
          _exwStyle,
          _className,
          _windowName,
          _wStyle,
          _x,
          _y,
          _width,
          _height,
          _hWndParent,
          _hMenu,
          _hInst,
          & ctrl);
        MessageBox (0, \"1\", \"\", MB_OK);
        if (_h == NULL)
          throw Exception (\"Window Creation Failed\");
        MessageBox (0, \"2\", \"\", MB_OK);
        return _h;
      }

      operator HWND () { return _h; }
    private:
      // Parametres passed to CreateWindowEx:
      DWORD _exwStyle;  // extended window style
      LPCTSTR _className; // pointer to registered class name
      LPCTSTR _windowName;  // pointer to window name
      DWORD _wStyle;  // window style
      int _x; // horizontal position of window
      int _y; // vertical position of window
      int _width; // window width
      int _height;  // window height
      HWND _hWndParent; // handle to parent or owner window
      HMENU _hMenu; // handle to menu, or child-window identifier
      HINSTANCE _hInst; // handle to application instance
      LPVOID _data;  // pointer to window-creation data
      // the window-handle:
      HWND _h;
  };
}

#endif
Avatar billede waldeinburg Nybegynder
02. november 2001 - 09:45 #22
De mange kald til MessageBox viser bare, hvordan jeg har fundet det sted, den går ned.
Den når til msgbox 8. Dvs. det er kaldet til std::strcpy i SetDefaults der får den til at gå ned. Men hvad i alverden har et kald til strcpy at gøre med en tilfældig variabel i en anden klasse???
Avatar billede waldeinburg Nybegynder
02. november 2001 - 11:34 #23
her er den makefile, jeg compiler med,hvis det kan hjælpe lidt.

dir = C:\\BCC55\\Filer\\WinLib\\\\

WinLibTest.exe : winlib\\direct3d.obj winlib\\procedure.obj main.obj
C:\\BCC55\\Bin\\ilink32.exe /Lc:\\bcc55\\lib;c:\\bcc55\\lib\\psdk\\dx8 /aa C0W32.OBJ winlib\\procedure.obj main.obj, WinLibTest.exe,, IMPORT32.LIB CW32.LIB

.cpp.obj :
c:\\bcc55\\bin\\bcc32.exe -Ic:\\bcc55\\include;c:\\bcc55\\include\\dx8 -c -n$: $(dir)$<
Avatar billede waldeinburg Nybegynder
02. november 2001 - 11:35 #24
hovsa! bare glemt den der winlib\\direct3d.obj, den skal ikke står der.
Avatar billede waldeinburg Nybegynder
02. november 2001 - 11:36 #25
I skal altså se bort fra den, det var ikke den, der var problemet eller noget (det kunne måske godt lyde sådan, da jeg skrev det)
Avatar billede waldeinburg Nybegynder
02. november 2001 - 12:33 #26
Nu har jeg fjernet strcpy kaldet (den var alligevel ikke nødvendig), og nu virker det.
MEN: Jeg udlover stadig pointene til den, der kan sige mig, hvorfor det gik ned af kaldet til strcpy, for jeg kunne jo gå hen og få brug for det igen.
Avatar billede joha Nybegynder
02. november 2001 - 16:16 #27
Svaret er ret simpelt:
Du kalder strcpy(\"New window\", _windowName) med \"New window\" som dest-parameter, men \"New window\" er readonly-memory og ikke en variabel.
Du overskriver altså noget tilfældig memory i dit program så det går ned.

Koden skulle istedet have været:
strcpy(_windowName, \"New window\");
Avatar billede waldeinburg Nybegynder
03. november 2001 - 14:19 #28
Den køber jeg ikke helt, joha. Jeg ved godt, at destinationen normalt står først i strcpy, men det synes min compiler ikke i dette tilfælde.
Under alle omstændigheder bliver en alm. streng i appostroffer tolket af compileren som const char * og destinationen er selvfølgelig erklæret som char *. Hvis du beder om en char * og giver en const char * brokker compileren sig højlydt, så du kommer aldrig så langt, at det kan gå ned på den måde.
Avatar billede waldeinburg Nybegynder
03. november 2001 - 14:28 #29
næh, undskyld, _windowName er jo ærklæret som const char *, så det var det, den var sur over. \"blabla\" er åbenbart ikke en const char * alligevel. Sorry!! Hvor dum har man lov til at være!!
Men: Nu har jeg prøvet at erklære _windowName som char * istedet, og at skrive parametrene i strcpy i rigtig rækkefølge, og det går stadig lige så lystigt ned.
Avatar billede waldeinburg Nybegynder
03. november 2001 - 14:29 #30
så der var altså ingen af os, der havde ret, joha :)
Avatar billede joha Nybegynder
03. november 2001 - 23:22 #31
Om \"blabla\" er en const char* er altid svært at vide, da det er helt op til compileren, hvor den placerer tekst-strenge , så som \"hej\".

VC++ 6.0 placerer f.eks. strengene i readonly memory, så der opstår en ulovlig-handling, hvis man prøver at overskrive dem.
Avatar billede alvion Nybegynder
04. november 2001 - 09:26 #32
  HWND Create (Controller & ctrl, char const * title)
  {
    _windowName = title;


Hmm... Skulle det istedet ikke være:

strcpy(_windowName, title);

Det er jo noget rigtig gris du laver. Du får _windowName til at pege på en streng uden for objektet.
Avatar billede waldeinburg Nybegynder
04. november 2001 - 18:43 #33
mmh, det kunne godt være, det skulle laves om. Det har ikke forvoldt problemer indtil nu, men jeg kan godt se din pointe. Nu må man håbe, det ikke begynder at gå ned. Vender tilbage, når det er rettet...
Avatar billede waldeinburg Nybegynder
05. november 2001 - 09:36 #34
Okay, jeg har gjort følgende:
char * _windowName;
i stedet for
LPCTSTR _windowName;
Og:
std::strcpy (_windowName, title);
i stedet for
_windowName = title;

Krads, bum, bang, så går det ned :(
Avatar billede alvion Nybegynder
05. november 2001 - 09:48 #35
Og det siger da også sig selv hvorfor.

char * _windowName
LPCTSTR _windowName;

i begge har du defineret en variabel som en pointer til chars, men du har ikke reserveret noget hukommelsesområde, som de skal pege på. Det betyder at _windowName peger på et tilfældigt område i hukommelsen. Når du så laver denne her:

std::strcpy (_windowName, title);

så forsøger du at skrive data fra title til et tilfældig sted i hukommelsen (hvad _windowName nu tilfældigvis peger på). DET MÅ MAN IKKE!

Prøv således:

char _windowName[200];

std::strcpy (_windowName, title);
Avatar billede waldeinburg Nybegynder
05. november 2001 - 09:49 #36
Jeg tror, jeg har fundet ud af det:
Hvis jeg allokerer hukommelsen før kaldet til strcpy, går det ikke ned. Altså
I Create:
_windowName = new char [std::strlen (title)];
std::strcpy (_windowName, title);
Og selvfølgelig en destruktor til at deallokere:
~DowMaker ()
{
delete _windowName;
}
Og en ny linje i SetDefaults, så vi ikke prøver at slette en NULL-pointer:
_windowName = new char;

Jeg troede egentlig, at strcpy selv fandt ud af at allokere. Skulle det ikke det?
Avatar billede alvion Nybegynder
05. november 2001 - 09:49 #37
Jeg er i øvrigt helt vild med dit minisite :-)
Avatar billede waldeinburg Nybegynder
05. november 2001 - 09:57 #38
Jeg tænkte lige på denne linje i constructoren:
DowMaker (char const * className, HINSTANCE hInst)
: _className (className),
Er det noget gris.
På den ene side: da den streng, der peges på, er nødt til at eksistere i det samme scope, som constructoren bliver kaldet i, gør det ikke noget.
Men på den anden side:
char * streng = new char;
DowMaker maker (streng, hInst);
delete streng;
DowMaker.Create ();
Da streng bliver brugt i Create, går det vel galt.
Hvis det er noget gris, hvad gør man så, hvis man har en char * const eller eller char &. De SKAL jo indlæses i constructoren.

Avatar billede alvion Nybegynder
05. november 2001 - 10:00 #39
Nej strcpy() finder IKKE selv ud af sådan noget - det er der faktisk ingen \"hukommelsesflytter\" funktioner, der gør. Du har ALTID ansvaret for at allokere og deallokere hukommelse i C/C++

Det ansporer også et vist krav til selvdisciplin. Det er så nemt at lave en funktion, der allokerer noget hukommelse og returnerer en pointer til denne (en nem måde at returnere komplekse variable på), hvorefter det er den kaldende funktions opgave at frigive hukommelsen. DET MÅ DU ALDRIG GØRE! Du hænger dig selv ganske langsomt.

Regel nr. 1: Hukommelse skal altid frigives i samme \"scope\", som det blev allokeret. Dvs. indenfor samme loop, funktion, objekt (constructor/destructor), etc.

Regel nr. 2: Hukommelse skal altid frigives i samme \"scope\", som det blev allokeret. Dvs. indenfor samme loop, funktion, objekt (constructor/destructor), etc.

Regel nr. 3: Hukommelse skal altid frigives i samme \"scope\", som det blev allokeret. Dvs. indenfor samme loop, funktion, objekt (constructor/destructor), etc.
Avatar billede waldeinburg Nybegynder
05. november 2001 - 10:02 #40
undskyld, dårlig formulering: Altså: _className bliver brugt i DowMaker::Create og _className peger på streng.
Avatar billede alvion Nybegynder
05. november 2001 - 10:10 #41
Kan du ikke zippe hele projektmappen og sende til mig? carsten@sarum.dk

Jeg skal nok uploade de vigtige rettelser her på eksperten.dk så vi overholder reglerne
Avatar billede waldeinburg Nybegynder
05. november 2001 - 13:03 #42
OK. Men det er ikke det, der fik det til at gå ned, vel?
Avatar billede alvion Nybegynder
05. november 2001 - 13:14 #43
Det er ikke til at sige. Send mig det hele, så er det nemmere at overskue
Avatar billede alvion Nybegynder
05. november 2001 - 15:40 #44
Hmm... Det er lavet i BC? Den har jeg desværre ikke, og dermed forsvinder min mulighed for at \"pille mig frem\" til resultatet...

Jeg synes, at du skal prøve at debugge dig igennem koden trin for trin. I den hvor programmet dør, undersøger du, om den/de pointere, du benytter, er oprettet med ovenstående regler i mente. Så skulle du meget gerne finde fejlen.
Avatar billede alvion Nybegynder
05. november 2001 - 15:46 #45
Jeg fandt lige et par smuttere alligevel:

_windowName = new char;
skal være
_windowName = new char[200];
ellers laver du blot en pointer til en enkelt char, og det er jo ikke nok :)

_windowName = new char [std::strlen (title)];
skal være
_windowName = new char [std::strlen (title) + 1];
ellers er der ikke plads til null-termineringen
Avatar billede waldeinburg Nybegynder
06. november 2001 - 09:14 #46
OK til den sidste, men den første kan være ligemeget. Den allokerer jeg bare, så jeg ikke kommer til at prøve at delete en NULL-pointer i destruktoren, hvis objektet slettes uden at have kaldet Create. Jeg skal forresten huske at delete den lige før jeg allokerer i Create.

Du kan hente BC gratis på borlands hjemmeside, hvis du vil.
Avatar billede alvion Nybegynder
06. november 2001 - 12:59 #47
Nej tak jeg har det fint med VC++ :-)

Jeg vil foreslå at du laver din destructor om:

~DowMaker ()
{
  if (_windowName)
    delete _windowName;
}


Så behøver du ikke allokere hukommelse til _windowName, før du skal bruge den. (Hvilket også var noget rod. Du Frigiver jo ikke den hukommelse, før du allokerer nyt til _windowName)
Avatar billede waldeinburg Nybegynder
06. november 2001 - 14:57 #48
Jeg tror jeg vil gøre det på en anden måde. Man kan godt kalde Create flere gange, så der skal alligevel frigøres før det nye kald til strcpy. Det skal altså se sådan ud:
      ~DowMaker ()
      {
        delete _windowName;
      }

      void SetDefaults ()
      {
        ...
        _windowName = new char;
        ...
      }

      HWND Create (..., char const * title)
      {
        delete _windowName;
        _windowName = new char [std::strlen (title) + 1];
        std::strcpy (_windowName, title);
      }

Men man kunne selvfølgelig også gøre det som du siger:


      ~DowMaker ()
      {
        delete _windowName;
      }

      void SetDefaults ()
      {
        ...
        _windowName = new char;
        ...
      }

      HWND Create (..., char const * title)
      {
       
delete _windowName;
        _windowName = new char [std::strlen (title) + 1];
        std::strcpy (_windowName, title);
      }

Avatar billede waldeinburg Nybegynder
06. november 2001 - 15:01 #49
Du får lige nogle point, alvion (selvom du kom med svaret på problemet mens jeg selv skrev mit svar ind :-).
Avatar billede alvion Nybegynder
06. november 2001 - 16:16 #50
Jamen jeg takker :)
Avatar billede waldeinburg Nybegynder
07. november 2001 - 14:07 #51
hov, det er jo noget værre vrøvl jeg skrev sidst. Vi retter lige:Men man kunne selvfølgelig også gøre det som du siger:


      ~DowMaker ()
      {
        if (_windowName)
          delete _windowName;
      }

      void SetDefaults ()
      {
        ...
      }

      HWND Create (..., char const * title)
      {
        if (_windowName)
delete _windowName;
        _windowName = new char [std::strlen (title) + 1];
        std::strcpy (_windowName, title);
      }

Jeg gik et eller andet galt, så de to forslag var ens :(
Avatar billede vivian22 Nybegynder
22. juli 2012 - 01:54 #52
Reklame.

Dette indlæg er blevet modereret af en CoAdmin

Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester