views:

309

answers:

4

I'm moving some old C code that generates a binary file into our C# system. The problem is, the resulting binary file will still need to be read by another old C program.

The original code outputs several structs to a binary file, and many of those structs contain linked lists, with *next pointers.

How can I write these in C# so that the original program will still be able to read them?

The old C code reads and writes the file a whole struct at a time, with freads and fwrites i.e.

fread ( &file, sizeof ( struct file_items ), 1, hdata.fp );

I can't find a whole lot of info on how fwrite would output the pointers, etc.

+3  A: 

If your code is depending on reading and writing pointer values to a file then it's broken. Every time you run the program it could potentially have a slightly different memory layout.

Instead of writing pointers you should probably convert the pointers into file offsets on write and convert the file offsets back to pointers on read.

(This is true for C, C++ and C#)

Aaron
I think we can assume that the pointers are re-filled after reading.
Henk Holterman
You're correct. Sometimes, sure, rather than having a separate C structure for I/O and one in memory for the real linked list, it's easier just to spit the linked list structures out whole (pointers and all) and then stitch them back together while reading them. When reading them in C#, just treat it like a 32 (or 64) bit value and ignore it.
clintp
@Henk - I disagree... based on the code given we can assume no such thing. Furthermore without dumping additional data out it would be difficult to impossible to re-fill the pointers after reading.
Aaron
@Aaron - For example, a singly-linked list is traversed from start-to-finish, writing out each structure to disk with the pointer value still in it (it's just along for the ride). Reading the file back, you simply re-read the fixed sized structures in one at a time, and stitch the pointers back together by ignoring the old values and putting in whatever valid values you need.
clintp
@clintp - I guess for a linked list (which I should have read that he mentioned) that would be true. I was thinking more of a tree or DAG
Aaron
+3  A: 

If the old code was writing pointers to a file, then odds are you dealing with very poorly written code. Those pointers would be meaningless to any other process reading that file...

Also, reading whole structures with a single fread() is a bad idea because different compilers may pad those structures differently (so the structure written by one application may be laid out differently than one read by another application).

dicroce
A: 

The only way you can be (correctly) writing pointers to disk is if you are using something like based addressing:

A linked list that consists of pointers based on a pointer can be saved to disk, then reloaded to another place in memory, with the pointers remaining valid.

Handling this in C# would be extremely difficult and require some kind of mapping layer during serialization.

Rob Walker
Handling this in C# would be _impossible_. The GC will move stuff around, and _fixing_ a lot of data for a long time is not an option.
Henk Holterman
The point is that using this format the file doesn't contain real pointers, just offsets. You could handle this in C# by mapping objects to offsets you assign ... difficult but not impossible.
Rob Walker
A: 

A pointer refers to a memory location, when you store a pointer in a file, it is meaningless, it refers to something that is ephemeral. So either it does not matter in this application because the data referenced is discared, or you have not stated the format correctly. Normally in such a case you would apply 'serialization', so that the data pointed to were also stored, in the file in such a way that the original data and what it pointed to could be reconstructed ('deserialized') at a later time.

There is no fundamental difference between file storage in C and C# - that is independent of the language, however there may be differences in structure packing, so just storing the structure was always a bad idea (structure packing can vary even between C compilers). Also of course you need to realise that a char type in C# is 16-bit, not 8. You need to let the existing storage format be the specification and then implement it in C# using serialisation to avoid problems with the differences in structure implementation.

Clifford