简体   繁体   中英

Error 0xC0000005: Access Violation when returning from a function C++

I am a beginner in this language and I have encountered this problem. After searching on net it seems it is related to memory allocation,pointers etc.. which I didn't quite understood.... Here I am trying to add data through class to a binary file... So I would like to ask what the problem can be-->

void addques()
{
    question abc;
    ofstream fout;
    fout.open("question.txt",ios::app|ios::binary);
    cout<<"Enter Question!\n";
    gets(abc.ques);
    cout<<"Enter Options!\n";
    gets(abc.option1);gets(abc.option2);gets(abc.option3);gets(abc.option4);
    cout<<"Enter correct option number\n";
    cin>>abc.k;
    cout<<"Enter question nummber"; cin>>abc.quesno;
    fout.write((char*)&abc,sizeof(abc));
    fout.close();
    cout<<"File closed";
}

It seems all the functions that have ifstream/ofstream class objects are showing this error. The last line "File Closed" is also being executed and after that errors shows up. Could it be this line-- fout.write((char*)&abc,sizeof(abc)) ; ??? Kindly Help

This is the related class-->

class question
{   public:
    char ques[80];
    char option1[50], option2[50], option3[50], option4[50];
    char k;
    char quesno;
};

For the whole program I pasted my code here http://pastebin.com/S7KNby0E Kindly see it...because I was unable to do so here

Are you entering a question or answer that's too long for one of your buffers? I'd bet you are, and it's overrunning the bounds of the class and corrupting the stack. Also, mixing cin and cout and the C style IO functions like gets is asking for trouble, so don't.

Since you're using C++, you don't have to do string manipulation as character arrays. There is a STL class that handles all of the memory crap for you. I'd rewrite your class in the following way:

class Question
{   public:
    string ques;
    string option1, option2, option3, option4;
    char k;
    char quesno;

    void write(fstream& f)
    {
        f << ques.length() << " " << ques << endl
          << option1.length() << " " << option1 << endl
          << option2.length() << " " << option2 << endl
          << option3.length() << " " << option3 << endl
          << option4.length() << " " << option4 << endl
          << k << " " << quesno << endl;
    }
};

and your function in the following way:

void addques()
{
    Question abc;
    ofstream fout;
    fout.open("question.txt", ios::app);

    cout << "Enter Question!" << endl;
    getline (cin, abc.ques);

    cout << "Enter Options!\n";
    getline(cin, abc.option1);
    getline(cin, abc.option2);
    getline(cin, abc.option3);
    getline(cin, abc.option4);

    cout << "Enter correct option number: ";
    cin >> abc.k;

    cout << "Enter question number: ";
    cin >> abc.quesno;

    // you will have to change your writing method a bit because you can't just write the string object straight to disk like you were before

    abc.write(fout);
    fout.close();
}

You should then be able to read one into a stream with the extraction operator in more or less the same way write works.

Ascii to Binary

Since you have to use binary, you can store the integer values as binary values in the following way:

int i = ques.length();
fout.write((const char *) &i, sizeof(i));

This will write the 32 bit integer value directly to the stream without converting it to a string first. Your strings will then have the following format:

+     0x0     0x1     0x2     0x3     0x4     0x5     0x6     0x7     
0x0  [0x00    0x00    0x00    0xC0  ][H       E       L       L
0x8   O       <space> W       O       R       L       D       <null> ]

The length is the first 4 bytes, shown here as 0x0000000C (integer value 12). The string follows immediately, and has the value "HELLO WORLD\\0". \\0 is the null terminator. In my example, this length includes the null terminator.

sizeof

Sizeof is an operator that produces the size in memory of the specified type as best as the compiler can determine. For integral types, such as int, short, char, etc, it will return the number of bytes used by the type. For arrays, you might run into confusing behavior. If called on an array declared statically to be of a fixed size, sizeof will return the array's length * the size of one element.

int derp[1000];
sizeof(derp); // sizeof(int) * 1000

If the compiler does not know how big the array is, what you will get is the size of a pointer to the first element. So be careful. You can't use sizeof on a pointer to determine array size.

int derp2[];
sizeof(derp2); // sizeof(int *), probably 4 or 8
int * derp3 = derp;
sizeof(derp3); // sizeof(int *), probably 4 or 8

To get the length of a std::string (the STL string class), use the length member:

string hurr = "hello world";
hurr.length(); // does NOT include the null terminator
               // length of string AND terminator is hurr.length() + 1

There's a clear problem, and many potential problems. Your symptom suggests a value got written into memory somewhere it shouldn't have (buffer overrun, floating pointer, etc).

Concerns

  1. Don't mix C++ standard stream I/O (std::cout, std:cerr, std:cin, std::ofstream, and many many more elements) with C-style standard I/O ( gets ). Choose one I/O library , and stick with it.

  2. Check and verify your assumptions regarding boundary conditions. Your boundaries in this case are the size of your input char arrays in question . Is your input data approaching/nearing the array sizes (the limits you defined)? Did you allow room for an extra terminating NULL (0) character at the end of each char array?

  3. Pre-initialize EVERYTHING you're going to be working with. What can your question constructor do to ensure neutral "empty data" exists in a new question ?

Strategy - Isolate the problem

  1. Comment out the entire function body (all statements), leaving the function empty. Run and verify that it works or not - this will identify if the problem is in the body, or somewhere else.

  2. start adding bits back in. Identify exactly what statement triggers the problem. There is concern, with access violations, that this type of code-triage may not reveal the true culprit.

EXCEPT: buffer overruns, floating pointers, and such can cause problems anywhere at anytime after the problem occurs. All the problem isolation in the world may not identify the source of the problem. You'll be developing skills to recognize common problems. The points above are intended to be some starting guidelines to help you develop those skills.

Style

  1. Declare each variable as near as possible to it's point of first use in the code. Consider moving the declaration for fout down.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM