Solved

fopen() quiz for my fellow experts.

Posted on 2004-10-13
29
1,171 Views
Last Modified: 2010-04-15
Hi guys,

I came across a less-than-obvious error the other day that I thought I'd share as a mini-puzzle.

A friend sent me some code (a C program).  After compiling it I tried to run it and found that the application was getting an error.  After stepping through the code, I discovered that the error lies here:

#include <stdio.h>

/*  function -- abbreviated here because it's quite long */
{
  char *cwd[80];
  FILE *fcb;

  fcb = fopen(str, "r");

  if (fcb == NULL)
  {
        getcwd (cwd, 80);
        printf("Failed to open %s (%d).  cwd=%s\n", str, errno, cwd);
        perror (" Open failure");
        return;
  }
}

I've run it several times, with str containing strings such as "TEST" and "C:\TEST".  Yet fopen () fails every time (returns NULL).  The files named in str DO exists.

The error messages resemble:

Failed to open TEST (0).  cwd=C:\DS\TH
Failed to open C:\DS\TH\TEST (0).  cwd=C:\DS\TH
etc.

The question is, why does fopen() always fail?

And to head off the obvious:

The file does exist.
The user/program is allowed read access to the file.
The file is not already open.
The system is Windows/XP.  (Meant as information, not an explanation!)


Let's see how good you guys really are.  :)
Kent
0
Comment
Question by:Kdo
  • 6
  • 4
  • 3
  • +9
29 Comments
 
LVL 23

Expert Comment

by:brettmjohnson
ID: 12305087
getcwd() is clearing errno [and perror()], so you are obscuring the true failure code.
I suspect you have reached the maximum number of open files for the process.
IIRC the default maximum number of open files is 20 for MS-DOS/Windows
(unless you explicitly override it).
0
 
LVL 16

Expert Comment

by:PaulCaswell
ID: 12306050
I'd guess that brett's idea is the most likely (errno == EMFILE) but there is one other possibility that you havent eliminated of errno == ENOMEM! This would happen if there is insufficient memory to allocate necessary blocks for the FILE * to use.

Paul
0
 
LVL 12

Expert Comment

by:stefan73
ID: 12306180
Hi ,
> getcwd() is clearing errno [and perror()], so you are obscuring the
> true failure code.

Good point. Split up the print, or store errno in a temporary variable before calling getcwd().

Cheers!

Stefan
0
 
LVL 45

Author Comment

by:Kdo
ID: 12307214

Rats.

I'd inserted the call to getcwd() for one of the tests to prove that the file was in the location that it was expected.  I didn't mean for it to muddy the waters.

The same code without the getcwd() (shown below) has similar results.

Kent



#include <stdio.h>

/*  function -- abbreviated here because it's quite long */
{
  char *cwd[80];
  FILE *fcb;

  fcb = fopen(str, "r");

  if (fcb == NULL)
  {
        printf("Failed to open %s (%d).\n", str, errno);
        perror (" Open failure");
        return;
  }
}

I've run it several times, with str containing strings such as "TEST" and "C:\TEST".  Yet fopen () fails every time (returns NULL).  The files named in str DO exists.

The error messages resemble:

Failed to open TEST (0).
 Open failure: Error 0

Failed to open C:\DS\TH\TEST (0).
 Open failure: Error 0
etc.


As much of a fit as that gave me, you'd think that I could at least get the question right.   ;(

sigh....


0
 
LVL 16

Expert Comment

by:PaulCaswell
ID: 12307738
Hmmmmmm!!! Gnarly!!

>>The question is, why does fopen() always fail?
Do you mean ALWAYS as in 'everywhere in the program' or it works everywhere else but here?

Were there any compiler warnings or linker warnings?

What is NULL defined as?

Are you using the correct libraries?

Paul
0
 
LVL 45

Author Comment

by:Kdo
ID: 12307929
>>Hmmmmmm!!! Gnarly!!

'Gnarly' -- where is that from????


>>Do you mean ALWAYS as in 'everywhere in the program' or it works everywhere else but here?

There are a number of fopen() calls in the application.  All of the others work just fine.  The other calls execute as part of the initialization process, this call is executed as a result of user interaction.


>> Were there any compiler warnings or linker warnings?

Several result is always 'false' and 'unreachable code' warnings during compilation from:

  if (DEBUG)
    Printf (....);


Several linker warnings for 'symbol is already defined'


>> What is NULL defined as?

The value established by the header files provided by the vendor.


>> Are you using the correct libraries?

Yes

0
 
LVL 16

Expert Comment

by:PaulCaswell
ID: 12308129
>>'Gnarly' -- where is that from????

http://www.cougartown.com/slang.html
Gnarly
Originally a difficult or large wave (He wiped out on a gnarly wave),later anything big or difficult (The Chemistry test was gnarly.), then later an expletive of approval (That custom paint job is gnarly!)

>>Several result is always 'false' and 'unreachable code' warnings during compilation from:

http://www.experts-exchange.com/Programming/Programming_Languages/C/Q_20888627.html?query=TFPRINT

As for the original question, I'm still thinking but I'm having difficulty (as I expect you originally did) seeing any way that the real fopen can return NULL without setting errno. Either errno is being cleared or the real fopen is not being called or is it something even more wierd.

Paul
0
 
LVL 22

Expert Comment

by:grg99
ID: 12308346
first you have char * cwd[80].  I suspect you meant "char cwd[80];"

What if "TEST":

(1)    Is a directory.  
(2)    Is a shortcut.
(3)    Is a named pipe.
(4)    Is a volume label.
(5)    Is a symbolic link to another volume that isnt mounted right now.
(6)    Has a bad block in its indirect block pointer table.
(7)     Is too big to open using a 32-bit file size fopen().






0
 
LVL 45

Author Comment

by:Kdo
ID: 12308422
>>first you have char * cwd[80].  I suspect you meant "char cwd[80];"

Yep.  (Programmers don't have to be able to spell -- they just have to spell the same way every time.  Of course, there are exceptions to this rule, huh???)


>> What if "TEST":

All good thoughts.  But none are the actual case here.


Kent
0
 
LVL 22

Expert Comment

by:grg99
ID: 12308869


(8)  Is a device, like CON, LPT, PRN.
(9)  Is a file with a Macintosh-like "Resource fork".
(10)  Is currently being compressed by the "compressed folder" DLL.
(11)  Is currently being defragmented.
(12)  Has too much auxiliary info to read into memory.
(13)  Has too many indirect blocks to read into memory.
(14)  Is a currently active VM swap file.
(15)  Is on a network drive with a very slow connection.
(16)  Had an indirect block marked bad by the drive itself, but not propagated up to the file system.
(17)  There's a virus-checker active that checks every file that's opened for viruses, and that file appears to have one.
0
 
LVL 45

Author Comment

by:Kdo
ID: 12309029

Hi grg99,

You've got lots of ideas, but on the wrong track.  The file is intact and stable.  It will open with notepad, wordpad, etc....


Kent
0
 
LVL 1

Expert Comment

by:meidanze
ID: 12309318
Hi,
1) I will advice you to restart the machine and login with local administrator.
    recompile and run the program
2) Try to chage str to other file just before the fopen and better print str just before the fopen and print the length  of the string you can overflow the memory.
3)try to copy the file to another directory and reopen it.
Hope it will help
0
 
LVL 16

Expert Comment

by:PaulCaswell
ID: 12309765
Kent,

Could there be another 'errno' in-scope with a value of 0.

Paul
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 9

Expert Comment

by:ankuratvb
ID: 12310208
Hi Kent,

You dont seem to be closing the file you opened with the fopen in the function.

If the function is called repeatedly,then you might've reached the max limit for the number of files that can be simultaneosly opened.

0
 
LVL 1

Expert Comment

by:JackNaif
ID: 12347057
Can we assume you didn't forget to protect the "\" in the file names?

"C:\\TEST" etc...
0
 
LVL 22

Expert Comment

by:grg99
ID: 12349231
How about:

(1)  There's a rogue "typedef something  FILE;"  or "#define FILE  something"

(2)  There's a fopen() function in scope that overrides the C library fopen().

(3)  You're on some OS like VMS that has files with specific "types"-- and you can't open a file of records with the regular fopen().

(4)  "str" is defined as a near pointer to char, and you're linking with the "far" or "huge" libraries.

(5) "str", the file name, is in Unicode and this fopen() doesnt accept Unicode.

(6)  Somebody has redefined fopen() to take a incompatible calling sequence, such as "Pascal", or "register".


0
 
LVL 16

Expert Comment

by:George Tokas
ID: 12381965
Hello Experts in C forum.
@Kdo:
First things first:
>>Failed to open TEST (0). //(0) means errno = 0... This means NO ERROR!!!!!  
>>cwd=C:\DS\TH
A NULL pointer returned from fopen().
Challenging!!!!
What about the value OPEN_MAX???
And HOW MANY FILES are allready oppened??
I reproduced that error using the following:
        for(i = 0; i < 100; i++){
        fcb = fopen(str, "r");
        if(fcb){
         printf("OK %s %s %d \n", str, cwd, i);}else
        {
         printf("Failed to open %s (%d).  cwd=%s  %d\n", str, errno, cwd);
         }
        }
When i > 46 I got the same error...
SO... You have opened the file many times OR you have MANY files opened allready...

Regards,

gtokas.
0
 
LVL 23

Expert Comment

by:brettmjohnson
ID: 12382427
gtokas,

>>Failed to open TEST (0). //(0) means errno = 0... This means NO ERROR!!!!!  

It has already been pointed out that the subsequent call to getcwd() clears errno.


> And HOW MANY FILES are allready oppened??

The too-many-open-files possibility has already been posited several times.
Kent has indicated that he has isolated the problem, but has yet to indicate
that any of the previous suggestions of too-many-open-files where his problem.

0
 
LVL 16

Expert Comment

by:George Tokas
ID: 12382649
@brettmjohnson
At my code snipet I don't use getcwd() and produced the same error when i > 46...

@Kdo
Try to change the value of OPEN_MAX to 100 in example. In BCB I'm using the default is 50.

gtokas.

0
 
LVL 16

Expert Comment

by:George Tokas
ID: 12388244
One more thing... I tried to run the same program at Win9x systems and the errors remain the samw... Allways when i > 46 the error appears...
As for my previous suggestion to Kdo...
I hacked a bit the _nfile.h and stdio.h to change the value of FOPEN_MAX...
The application LOOKS LIKE changed the values but the result was the same....
So IMHO that have to deal with windows itself OR with the libraries linked to the executable.....
Also IMHO to try to solve this matter programmatically will be a waste of resources except of course if it will be done for academic and/or expearience reasons.
Btw... In my snippet above I changed:
FILE *fcb;-> FILE *fcb[100];// allocated buffers for 100 files.
And of course I opened the files using fcb[i] = fopen.....
The same result when i > 46...
That means IMHO again that too many files have opened ans never closed with fclose.
Maybe it is needed a change in design flow strategy about opening files and that mean to open file load to buffer and close...

Regards,

gtokas.
0
 
LVL 16

Expert Comment

by:PaulCaswell
ID: 12531301
gtokas,

FYI, here's some code that will extend the number of files you can open. This is almost certainly NOT the problem Kent was demonstrating in his question. I hope he tells us the answer soon.

// Allow more files.
// How many files you want.
#define MAXFILES 100
// The new _iob table.
FILE __near __cdecl _iob [MAXFILES];
FILE __near * __lastiob = &_iob[MAXFILES-1];
// Import the _nfile .
extern int _nfile;
// Request more files. Call this near the start of main.
void MoreFiles ( void );
// Request more files.
void MoreFiles ( void )
{
      union REGS      InRegs, OutRegs;
      // Call int 21 function 67.
      
      InRegs.x.ax = 0x6700;
      InRegs.x.bx = MAXFILES;
    intdos( &InRegs, &OutRegs );
      
      if (!OutRegs.x.cflag)
      {
            // Thats the max number of files now.
            _nfile = MAXFILES;
      }
      else
    {
            TFPRINT (("MoreFiles Failed"));
      }
}

Paul
0
 
LVL 16

Expert Comment

by:PaulCaswell
ID: 12531334
Kent,

>>Several linker warnings for 'symbol is already defined'
Were any of them 'file' related such as 'errno', 'fopen' '_iob'.

Paul
0
 
LVL 3

Expert Comment

by:Mister_N
ID: 12933253
#include <stdio.h>
#include <stdlib.h>

int main ()
{
  #define str "test"
  char cwd[80];
  FILE *fcb;

  fcb = fopen(str, "r");

  if (fcb == NULL)
  {
        printf("Failed to open %s (%d).\n", str, errno);
        perror (" Open failure");
        return;
  }
}

....... ^_____^ this works fine for me so where"s the problem?
0
 
LVL 3

Expert Comment

by:Mister_N
ID: 12933266
perhaps check for your string to be well terminated...
otherwise i'm missing something...
0
 
LVL 8

Expert Comment

by:ssnkumar
ID: 13071250
I tried the same on Linux and it is working without any problems!
The problem can be that the string is having a newline ('\n') character in the end......
0
 

Accepted Solution

by:
modulo earned 0 total points
ID: 13151570
PAQed with no points refunded (of 100)

modulo
Community Support Moderator
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now