Thread overview
Okay, I'm stumped - Crashing on the first fprintf or fwrite after successfully opening a file with fopen(filename, "wb").
Mar 03, 2005
SL
Mar 03, 2005
Arjan Knepper
Mar 03, 2005
SL
March 03, 2005
This is some test code that isn't working:
void freeze ()
{
	printf("Opening [%s]\n", situation_file);
	FILE *fh = fopen(situation_file, "wb");
	if (fh==NULL) return;
	fprintf(fh, "This is a test.\n");
	...
	(There's a bunch of fwrites below there, and eventually an fclose, but it's not getting past the fprintf)

What's happening is, the path is correct, the file is being opened fine and cleared when it's opened, but it crashes on the fprintf line. (P.S. I have 1.7 GB of free HD space, and other programs can write to the HD just fine, even the DOS version of this program. I can modify that file  in SciTE without any trouble either.

Originally there was no fprintf, and it was crashing on the first fwrite - I initially added the fprintf to find out if the crash was due to the variable being written (Since it wouldn't be crashing on the fprintf line if it was due to the variable).

It's an "Access violation - code c0000005" by the way.

This is that section of code in asm (from the disassembly provided by WinDbg):
	image00400000!freeze:
	004037c5 c8040000         enter   0x4,0x0
	004037c9 ff35f0744400 push dword ptr [image00400000!situation_file (004474f0)] ds:0023:004474f0=004474dc
	004037cf 686c524400       push    0x44526c
	004037d4 e8c7220300       call    image00400000!printf (00435aa0)
	004037d9 687a524400       push    0x44527a
	004037de ff35f0744400 push dword ptr [image00400000!situation_file (004474f0)]
	004037e4 e857220300       call    image00400000!fopen (00435a40)
	004037e9 8945fc           mov     [ebp-0x4],eax
	004037ec 83c410           add     esp,0x10
	004037ef 85c0             test    eax,eax
	004037f1 7502             jnz     image00400000!freeze+0x30 (004037f5)
	004037f3 c9               leave
	004037f4 c3               ret
	004037f5 687d524400       push    0x44527d
	004037fa ff75fc           push    dword ptr [ebp-0x4]
	004037fd e8c22b0300       call    image00400000!fprintf (004363c4)
	00403802 83c408           add     esp,0x8


I can't for the life of me come up with any possible reason why this should be opening fine, clearing the file, and then crashing as soon as it tries to write something.

So I tried following it into fprintf. Each time it crashed on a call, I restarted it, got back to that spot, and stepped into that call, and continued until it crashed again, repeating the procedure. This is how it went: fprintf called vfprintf which called _pformat which called _fputc_nlock which called _flushbu which called setvbuf which called malloc, which crashes while calling RTLMultiPool::Alloc
	00437591 8b0d90b74400 mov ecx,[image00400000!RTLMultiPool::pMainHeap (0044b790)]
	00437597 e824450000       call   image00400000!RTLMultiPool::Alloc (0043bac0)

This was the state when it called RTLMultiPool::Alloc:
eax=00000c4c ebx=0044ab8c ecx=0044dc24 edx=00000001 esi=00000000 edi=00004000
eip=00437597 esp=0012fc18 ebp=0012fc30 iopl=0         nv up ei pl zr ac po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000 efl=00000256
image00400000!malloc+0x2b:
00437597 e824450000       call   image00400000!RTLMultiPool::Alloc (0043bac0)

I didn't follow it beyond there.

A few more things:
1) It can't be an incorrect path; It's successfully opening the file and clearing it (I tested by adding some gibberish to the file and saving, then running the program. It does indeed open the file and clear it before crashing).
2) The file isn't locked, if it were I wouldn't be able to modify it from ScITE or other programs, and fopen would have failed.
3) situation_file is correct, it's printf'd so I could make sure of that. It's a constant. Oh, and it fopens the same file earlier, and yes, it's all successful, and yes, it fcloses it afterwards (I double-checked). It doesn't open that file anywhere else in the program.
4) I can even set a breakpoint on the printf("Opening [%s]\n", situation_file); line, and when it reaches it, open up that file that situation_file refers to in SciTE, type some characters, save it, and close it, and check - it was indeed written, nothing prevented it, the file definitely isn't locked.

Anyone have any clue WTF is going on? I'm out of ideas.

-SL
March 03, 2005
SL wrote:
> This is some test code that isn't working:
> void freeze ()
> {
>     printf("Opening [%s]\n", situation_file);
>     FILE *fh = fopen(situation_file, "wb");
>     if (fh==NULL) return;
>     fprintf(fh, "This is a test.\n");
>     ...
>     (There's a bunch of fwrites below there, and eventually an fclose, but it's not getting past the fprintf)

Tried this code with the latest beta, no problem.

What compiler version are you using? What is the target platform? Using static libs or dynamic RTL lib? What is the lib and include path set to?

Arjan
March 03, 2005
Arjan Knepper wrote:
> SL wrote:
> 
>> This is some test code that isn't working:
>> void freeze ()
>> {
>>     printf("Opening [%s]\n", situation_file);
>>     FILE *fh = fopen(situation_file, "wb");
>>     if (fh==NULL) return;
>>     fprintf(fh, "This is a test.\n");
>>     ...
>>     (There's a bunch of fwrites below there, and eventually an fclose, but it's not getting past the fprintf)
> 
> 
> Tried this code with the latest beta, no problem.
> 
> What compiler version are you using? What is the target platform? Using static libs or dynamic RTL lib? What is the lib and include path set to?
> 
> Arjan

I'm using the latest beta, on windows. I just checked, the function (freeze) works fine near the start of the program, after unfreeze was called, for instance. So something in the program somewhere is screwing something up, but I hadn't thought of any way to find it. Now it occured to me that I can place calls to freeze() in particular places in the code and recompile (normally it's only called at the very end of the program), and attempt to narrow down when the problem first appears.

Target platform is windows. As for static libs or dynamic RTL lib, whichever is default. The compile line I'm using is:
	dmc.exe -ownoctis.exe -DALL -DWINDOWS noctis.cpp noctis-0.cpp noctis-1.cpp noctis-2.cpp win.cpp noctis.def gdi32.lib shell32.lib -mn -5 | more
And for the debug build:
	dmc.exe -L/co/DETAILEDMAP/LINENUMBERS -oD_wnoctis.exe -DALL -DWINDOWS -DDEBUG -D -g noctis.cpp noctis-0.cpp noctis-1.cpp noctis-2.cpp win.cpp dnoctis.def gdi32.lib shell32.lib -mn -5 | more

*checks*

Lib is [] Include is ["D:\Program Files\Microsoft Visual C++ Toolkit 2003\includ
e";"C:\Program Files\Microsoft SDK\include"] Path is [c:\beta\dm\bin;c:\windows\
system32;c:\windows;c:\windows\command]

That's odd. Well I was deliberately clearing lib, since DMC was choking if it pointed to the MS SDK for some reason. I hadn't touched include, since it seemed to work.

I've set them to point at c:\dm\lib and c:\dm\include now, though I can't test whether it fixes the crash, since it started failing in OTHER places now (before I changed lib and include, actually).

Now I can't seem to convince DMC to make this struct two bytes long (and this is apparently causing crashes due to trying to write outside some pvlist arrays, since they're allocated to a specific size in bits, not to a specific number of elements):
struct pvlist {
	Uword polygon_id : 12;
	Uchar vtxflag_0  : 1;
	Uchar vtxflag_1  : 1;
	Uchar vtxflag_2  : 1;
	Uchar vtxflag_3  : 1;
}
It's coming out as 4 bytes, or 3 if I do #pragma pack(1). But those bit amounts total 16, so you'd think it would be 2 bytes (It is in BC too). I can't make polygon_id a Uchar, because then the compiler complains that "12 exceeds maximum bit field width of 8 bits." Moving polygon_id after the flags doesn't make the struct any smaller either. Hm.

There was another struct with four two-bit variables which was coming out larger than it should have been, but that one started working after I changed each variable's 'type' to Uchar (It was Uword).

If I omit the type from polygon_id's declaration (This surprisingly (to me) actually compiles), the thing becomes 5 bytes long. (!)

Well I'm hoping this somehow is the reason for the crash in RTLMemory::Alloc.