1

I have a VC++ application and in my application i have some basic file operations.

Below is the defaulting code

CStdioFile cFile;
CFileException e;
CString sReport;
CString sHtmlfile = "testreport.html"
OutputDebugString((sHtmlfile));
if (!cFile.Open(sHtmlfile,CFile::modeCreate | CFile::modeWrite, &e ))
{
}

The problem is my application executes this piece of code every few minutes. and it works fine.

After several runs of the code the cFile.Open() function fails. I tried to get the error message

TCHAR szError[1024];
e.GetErrorMessage(szError,1024);
OutputDebugString((szError));

The irony is the szError error message is "No error occured".

This again works once i restart my application. Any idea why this occurs.

Thanks in advance.

ckv
  • 10,539
  • 20
  • 100
  • 144
  • Please indent your code so it is formatted. (just mark it and click on the code button). – Björn Pollex Mar 24 '10 at 09:26
  • 2
    This code reminds my why I hate MFC. – sbi Mar 24 '10 at 09:33
  • 4
    My first guess would be that, under certain circumstances, the file is not being closed. But since you seem sure that it is being closed, what other processes are using the file? A web browser? Could anything else be reading the file (and have it open with `shareDenyWrite` or a similar mode) at the time you are trying to open it? – Nate Mar 24 '10 at 16:06

3 Answers3

2

Do you have multiple instances running? I suggest you use Process Explorer when the error occurs to see if any other handles to the said file exist.

And GetLastError will report the error reported by the last API function. If there were any other API calls between the failing API call and the call to GetLastError, then the last error value is overwritten. (As @sbi has already pointed out in the comments.)

Agnel Kurian
  • 57,975
  • 43
  • 146
  • 217
  • No i dont have multiple instances running. Let me see if i can use process explorer. Yes true but i dont call any other API so that the last error value cant overwrite. You can refer the code above. – ckv Mar 29 '10 at 08:35
  • 1
    There could be other API calls within the `CStdioFile::Open` class. The source for 'CStdioFile' comes along with MFC... might help to have a look (though experience says otherwise). – Agnel Kurian Mar 29 '10 at 08:54
  • What exactly do you do with the file once it opens successfully? – Agnel Kurian Mar 29 '10 at 09:07
  • Once i open the file i fill it with many contains something like a report of some data and then i mail the file to few email addresses. And finally of course i close the file. – ckv Mar 29 '10 at 09:59
  • I got the process explorer installed. Can you explain how i can effectively make use of it to find out the file problem – ckv Mar 29 '10 at 10:22
  • THe process explorer just shows the private bytes and working set. How is this going to help me. – ckv Mar 29 '10 at 10:29
  • Sorry but i am not quite sure what you want me to search. I understand the Find handle but cant make much out of it. If you can explain it in more detail it would be of great help – ckv Mar 29 '10 at 12:16
  • 1
    Search for `testreport.html`. This should give you a list of all open file handles to the said file. Also, lists the name and PID of the process which has the file open. – Agnel Kurian Mar 29 '10 at 13:47
  • Ok Thanks i shall run the same and let u know the results. It will take atleast 6 hours for me to reproduce the issue. – ckv Mar 29 '10 at 13:57
  • Well the issue was reproduced but i couldnt find any handles to the file names in the process explorer. – ckv Mar 30 '10 at 04:03
  • Well the issue was reproduced but i couldnt find any handles to the file names in the process explorer. And this issue comes like after the service goes through this code for around 500 times and each of the 500 times i get the email with the corresponding html file and then it just stops because it fails in CFile::Open() – ckv Mar 30 '10 at 04:33
  • That's tricky. I was thinking that you could put a breakpoint somewhere and then then search for handles when the call to Open fails. I am almost out of ideas here. Last shots: try disabling your anti-virus program, try using a different disk. – Agnel Kurian Mar 30 '10 at 05:29
  • Yes i shall probably try that. Actually i wanted to add that this does not happen in all machines. – ckv Mar 30 '10 at 06:21
  • Well i just found that the files are getting created with size 0KB but i am not able to use them as the exception still occurs. Could this be a handle problem. – ckv Apr 01 '10 at 11:23
  • Looks like a handle problem at first sight. But since you mentioned that this does not happen on all machines, it could be other things... – Agnel Kurian Apr 05 '10 at 10:14
1

Maube you forget to close your file and it come out of file descriptors. They are all closed when you quit your application, then you can run it again. Check if your files are closed or not.

OK. If this is not the above case, what could it be ? You get the error message from cFile.Open, hence we can believe it's accurate.

I'm not sure what would happen if another file of the same name is already open by the current process, or if you try to open a file with a strange name, like empty string. To sort these out you can also print the name of the file you are opening with the error (and also trace the cases where no error occurs).

kriss
  • 23,497
  • 17
  • 97
  • 116
  • The CFile.Close is called at the end of this function. So that must not be the problem – ckv Mar 24 '10 at 09:32
  • 2
    @viswanathan: This is only true if the `cFile.Close()` is actually executed. If you have to do this manually, there's a good chance that an exception prevents it from execution. (Or an early `return` for all we know. We haven't seen your code.) That's what RAII is for. – sbi Mar 24 '10 at 09:53
  • Well it can be rest assured that the CFile.Close() actually executes. There are no return statements prior to that. I have verified that by stepping through the code. – ckv Mar 24 '10 at 09:58
  • @viswanathan: I have learned the hard way not to assume anything unless proven. Have you checked whether the file is already opened when the opening failed using some of the tools available? (What's its name? FileMonitor?) – sbi Mar 24 '10 at 20:39
  • I am yet to probe further on that. But if the exception says "No Error Occured" it got to mean something. I couldnt find any relevant documentation regarding this error in MSDN. Still working out with the code – ckv Mar 25 '10 at 04:27
  • 1
    @viswanathan: Note that the message "No error occurred" could also be an error in itself. This sounds like what `GetLastError()` reports. If the library code calls any other API between the failing one and calling `GetLastError()`, the message is misleading. – sbi Mar 26 '10 at 17:57
  • As you can see from the code above i dont call any other API between the failing one and calling GetLastError(). – ckv Mar 29 '10 at 08:26
  • @viswanathan: Indeed, but not knowing MFC, I wouldn't know about `CStdioFile::Open()`. – sbi Mar 29 '10 at 21:58
1

You are using C++. Your error could be completely somewhere else. I've had a pointer bug that resulted in clean code coughing up an error.

Have you tried building in release mode?

I would suggest trying to step through and perhaps narrow down where your error appears.

PLG
  • 448
  • 5
  • 21
  • I have stepped through the code and i could find out that it failed exactly in CFile::Open(). When i run the same in release build also i can reproduce the issue with same results. What more should i try? – ckv Mar 30 '10 at 04:42
  • try adding NULL as the third parameter for Open() and surround the function call in a try/catch section catching CFileException. I assume this from the docs, "While the CFile constructor will throw an exception in an error condition, Open will return FALSE for error conditions." I also see that you most likely copied the example from the Open docs. On definite distinction is that they use a char* and you are using CString. Are you sure that CString is casting to LPCTSTR correctly? – PLG Mar 30 '10 at 17:13
  • Another suggestion which hinges on my previous post is... to check to see if the address space of your CString is not being overwritten at some point. That would be the sign that your error is wild pointer related. – PLG Mar 31 '10 at 11:12
  • Well i just found that the files are getting created with size 0KB but i am not able to use them as the exception still occurs. Could this be a handle problem – ckv Apr 01 '10 at 11:28
  • If that is the case, then my first guess would be that 'CFile::modeWrite' is failing. Is the close() not happening fast enough so that you get a contention error? Perhaps add a counter to the name of the file and see if the error persists. So your files will be testreport1.html, testreport2.html, etc... Why are you opening and closing the file rapidly anyways? If you keep writing to the same file over and over, then why not have an instance variable that holds the open file and closes it after you are completely done with it? – PLG Apr 01 '10 at 11:40
  • For your information i dont open the same file over and over again. I open different files with different file names just for a sample i wrote that code. And it is not really that fast everyhting goes in sequential order only until one file is closed the other wont open. – ckv Apr 01 '10 at 13:39