0

I am working on a MFC application witch needs to store data on a file

I have a class like this

class Client
{
public:
    Client(CString Name , CString LastName , CString Id );
    int create();
    int update(Client & myClient);

    CString name;
    CString lastName;
    CString id;
};



Client::Client(CString Name , CString LastName , CString Id )
{
    name = Name;
    lastName=LastName;
    id=Id;
}

void displayMessage(CString message , CString title=L"Meesage")
{
    MessageBox(NULL,message,title,MB_OK | MB_ICONERROR);
}


    int Client::create(Client myClient)
    {
        ofstream output;
        output.open("test.dat" , ios::binary );
        if( output.fail() )
        {
            CString mess;
            mess = strerror( errno );
            displayMessage(mess);
            return 1 ;//anything but 0
        }


        output.write( (char *) &myClient , sizeof(Client));
        output.close();

        return 0;
    }


    int Client::update(Client & myClient)
    //also tried passing by value : int update(Client myClient)
    {
        ifstream input;
        input.open("test.dat" , ios::binary );
        if( input.fail() )
        {
            CString mess;
            mess = strerror( errno );
            displayMessage(mess);
            return 1 ;//anything but 0
        }


        input.read( (char *) &myClient , sizeof(Client));
        input.close();

        return 0;
    }

Create function works well ,

But , about update function I have some problems

I use function like this:

Client myClient();
myClient.update(myClient);

But I got this error when I run this function

 Unhandled exception at 0x5adfab2a (mfc100ud.dll) in MyProject.exe: 0xC0000005: Access violation writing location 0x039708fc.

What Can I do?

Arashdn
  • 691
  • 3
  • 11
  • 25
  • why are you doing `input.read( (char *) &myClient , sizeof(Client));` and `output.write( (char *) &myClient , sizeof(Client));`? what is the *complete* definition of `Client`? – Andy Prowl Jan 19 '13 at 15:11
  • 1
    You can run your program in a debugger. – Some programmer dude Jan 19 '13 at 15:12
  • As a hint where to look for the problem, if the class has pointers they can't be saved as it's the actual pointer that is saved and not what it points to. When you read it, the pointer will just point to some "random" memory. – Some programmer dude Jan 19 '13 at 15:26
  • 1
    Read about the [implicit `this` pointer](http://msdn.microsoft.com/en-us/library/y0dddwwd%28v=vs.80%29.aspx) present in (nonstatic) member functions. – Drew Dormann Jan 19 '13 at 15:33
  • complete body of class added .... – Arashdn Jan 19 '13 at 16:22

2 Answers2

2

Careful. Client myClient(); declares a function named myClient. Writing to an address of a function is going to cause some issues, like crashing. Just change it to Client myClient; (that way you're creating an actual Client object, and then actually writing to an object). Of course, I hope writing to a Client object like that is safe (see Joachim Pileborg's comment about pointers, for example).

For example, look at the following code:

#include <typeinfo>
#include <iostream>

struct S {};

int main()
{
    S s1();
    S s2;
    std::cout << typeid(s1).name() << std::endl;
    std::cout << typeid(s2).name() << std::endl;
}

The results (using g++) print out:

F1SvE
1S

The important point is that they are not the same! s1 is a declaration of a function named s1 that takes no parameters and returns an S. s2 is an actual S object. This is known as C++'s "most vexing parse" (because it can cause a lot of frustration).

Edit: Oh boy, you keep updating your question with more (actual) code, and that keeps changing things. For future reference, just start with the complete actual code so people don't have to keep changing things :)

You can't safely write CStrings like that. They store pointers internally, and like Joachim Pileborg mentions, that'll wreck havoc when trying to read them in.

Additionally, Client has no default constructor anymore (because you've provided your own constructor). So you can't say Client myClient; anymore either. You'll have to use the right constructor.

Community
  • 1
  • 1
Cornstalks
  • 37,137
  • 18
  • 79
  • 144
  • My main class has a constructor which needs three arguments to work , I can't create an object with out arguments ... – Arashdn Jan 19 '13 at 16:18
  • @Arashdn: I'm not saying get rid of parentheses always. I'm saying get rid of the parentheses you don't need. The empty ones. If you've got arguments you're passing, go ahead and use parentheses and pass the arguments. But if you are passing zero arguments, don't use parentheses. Like I said, just say `Client myClient;`. zero arguments = zero parentheses. More than zero arguments = parentheses. – Cornstalks Jan 19 '13 at 16:23
  • @Arashdn: I don't expect you to be an expert :) I'm just trying to clearly explain. – Cornstalks Jan 19 '13 at 16:28
  • So , What is the solution to store CString s in a file? – Arashdn Jan 19 '13 at 16:32
  • @Arashdn: That's up to you. Look up "serialization" because it looks like you're trying to serialize your `Client` class. – Cornstalks Jan 19 '13 at 16:34
0

You cannot store CString contents as a binary data. You must use fprintf, CStdioFile::WriteString or similar thing to write data. CString doesn't have constant-size buffer, and hence the address-of would be invalid.

My suggestion it to break the learning problem into parts - practice CString, file-io, class design and the UI as different aspects. Don't mix them all, unless you get comfortable with other aspect. You'll not know what the problem was.

Also, the code you posted as obvious error: create method doesn't have any parameter in class, but while implementing you have a parameter!

Ajay
  • 18,086
  • 12
  • 59
  • 105