(Link to AcmlmWiki) Offline: thank ||bass
Register | Login
Views: 13,040,846
Main | Memberlist | Active users | Calendar | Chat | Online users
Ranks | FAQ | ACS | Stats | Color Chart | Search | Photo album
05-03-24 12:10 PM
0 users currently in Programming.
Acmlm's Board - I3 Archive - Programming - Memory Buffer/Array Overlays New poll | |
Add to favorites | Next newer thread | Next older thread
User Post
Guy Perfect









Since: 11-18-05

Last post: 6285 days
Last view: 6284 days
Posted on 12-12-06 05:39 PM Link | Quote
This is nothing special at all, but as a BASIC veteran, I appreciate how flexible C can be when dealing with memory and arrays.

What this program does is allocate a set number of bytes in memory, declares an array and refers it to somewhere inside the allocated memory, modifies some values in the array, then writes the block of memory to a file.

Again, stupid simple, but having worked with BASIC for most of my programming life, I find this kind of thing very entertaining.

#include <stdio.h>  // Needed for FILE, fopen, etc.
#include <stdlib.h> // Needed for calloc, free, etc.

// A simple 3-byte structure. Only for testing

typedef struct {
char NumA;
char NumB;
char NumC;
} TestStruct;

void main() {
// Remember that MSVC++ likes C variables declared at top
char *Buffer; // In-memory buffer pointer
TestStruct *TestArray; // In-buffer array pointer
FILE *FilePtr; // File I/O stream pointer

// Essentially the same as:
// Dim Buffer(0 to 63) As Byte

Buffer = calloc(64, 1);
// calloc() sets memory to 0. malloc() only allocates
// ReDim: void *realloc(void *ptr, size_t size);

// Uses a pointer as an array at location Buffer + 1
// Buffer + 1 starts at the second byte, not the first

TestArray = (TestStruct*) (Buffer + 1);

// Sets a couple of elements
TestArray[0].NumA = 16;
TestArray[0].NumB = 32;
TestArray[0].NumC = 48;

TestArray[1].NumA = 1;
TestArray[1].NumB = 5;
TestArray[1].NumC = 10;

// Essentially the same as:
// Open "C:\Test.dat" For Binary Access Write As FilePtr
// Put FilePtr, 1, Buffer
// Close FilePtr

FilePtr = fopen("C:\\Test.dat", "wb");
fwrite(Buffer, 64, 1, FilePtr); // The 1 here is element size
// fread() works with the same arguments
fclose(FilePtr);

// IMPORTANT: Deallocate the buffer. Not required in BASIC
free(Buffer);

// Not required, but good habit
return;
}
Cellar Dweller +

Red Koopa









Since: 11-18-05
From: Arkansas

Last post: 6293 days
Last view: 6283 days
Posted on 12-14-06 01:30 AM Link | Quote
Using structs to read or write file or network data is risky. The endianess, padding, size, and perhaps even order of structure members can vary depending on the CPU architecture, compiler, and compiler options. Even reading or writing file data directly into individual variables or casting a pointer from inside a file buffer to another data type is unsafe due to endianess, alighnment, and type size issues.

The safest practical method for handling file data is to use the types from stdint.h and shift individual bytes to or from the file out of or in to the correct position in your program's variables. For example, this a inline function I wrote to read 64 bit big endian integers from a file buffer :
static inline uint64_t rbeu64(char *p)

{
return ( (((uint64_t)(((unsigned char *)p)[0]))<<56)
| (((uint64_t)(((unsigned char *)p)[1]))<<48)
| (((uint64_t)(((unsigned char *)p)[2]))<<40)
| (((uint64_t)(((unsigned char *)p)[3]))<<32)
| (((uint64_t)(((unsigned char *)p)[4]))<<24)
| (((uint64_t)(((unsigned char *)p)[5]))<<16)
| (((uint64_t)(((unsigned char *)p)[6]))<<8)
| ((uint64_t)(((unsigned char *)p)[7])) );
}
If I needed to read a little endian integer, I'd use the same technique.
Jagori

150


 





Since: 11-17-05

Last post: 6284 days
Last view: 6284 days
Posted on 12-14-06 01:36 AM Link | Quote
I've gotten so used to the freedom that C gives with memory that I often have to rethink how I do things when I'm working in a language that doesn't work that way. It can make for some pretty dirty hacks that actually work, but of course you need to be very careful with that.

It just sucks when you do it by accident. Like array++ instead of array[0]++, or stuff like that. I once misused realloc() and ended up with my program trying to use one array squarely inside the memory space of another array, and the only symptom was some weird results of simple operations. Still, I'd rather have to deal with that kind of thing than not have the freedom to do it.
Guy Perfect









Since: 11-18-05

Last post: 6285 days
Last view: 6284 days
Posted on 12-14-06 01:57 AM Link | Quote
That's very informative, Cellar Dweller, but the purpose of that snippit is to demonstrate various ways of working with a block of memory, not working with file data.
HyperHacker

Star Mario
Finally being paid to code in VB! If only I still enjoyed that. <_<
Wii #7182 6487 4198 1828


 





Since: 11-18-05
From: Canada, w00t!
My computer's specs, if anyone gives a damn.
STOP TRUNCATING THIS >8^(

Last post: 6284 days
Last view: 6284 days
Posted on 12-14-06 06:41 AM Link | Quote
Originally posted by Jagori
It just sucks when you do it by accident. Like array++ instead of array[0]++, or stuff like that. I once misused realloc() and ended up with my program trying to use one array squarely inside the memory space of another array, and the only symptom was some weird results of simple operations. Still, I'd rather have to deal with that kind of thing than not have the freedom to do it.

Yes, memory corruption - particularly from misuse of arrays (treating an array of pointers to objects as an array of objects is a fun one) - is annoying because the symptoms tend to be completely bizarre. I find generally the program will just crash at random in some completely unrelated routine. For example fclose()ing an already-closed file is supposed to be safe, but it was crashing because of some place where I'd written an array wrong that had nothing to do with files.
Cellar Dweller +

Red Koopa









Since: 11-18-05
From: Arkansas

Last post: 6293 days
Last view: 6283 days
Posted on 12-15-06 07:57 AM Link | Quote
The reason I brought up the file stuff is because structure overlays are a popular but often unwise technique for handling data that originated from or is destined to somewhere outside the program. Also, the example program did write to a file.

I wouldn't think a double fclose() to be safe. The fact that file streams are pointers suggests that they point to data on the heap. The first fclose() free()s the FILE structure, and if an attempt is made to call fclose() again, the program would probably segfault or cause a double free(), which would probably cause a segfault later.

Not too long ago, a program I was working on had a wierd segfault bug that was driving me nuts. By using Electric Fence I found out I had a double free() in it.
HyperHacker

Star Mario
Finally being paid to code in VB! If only I still enjoyed that. <_<
Wii #7182 6487 4198 1828


 





Since: 11-18-05
From: Canada, w00t!
My computer's specs, if anyone gives a damn.
STOP TRUNCATING THIS >8^(

Last post: 6284 days
Last view: 6284 days
Posted on 12-17-06 12:50 AM Link | Quote
It might be fclose()ing a NULL pointer I was thinking of, but either way, something that should be safe was instead going boom. I know double free() is a bad thing in any case.
Add to favorites | Next newer thread | Next older thread
Acmlm's Board - I3 Archive - Programming - Memory Buffer/Array Overlays |


ABII

Acmlmboard 1.92.999, 9/17/2006
©2000-2006 Acmlm, Emuz, Blades, Xkeeper

Page rendered in 0.013 seconds; used 383.57 kB (max 464.08 kB)