I'm writing a program that writes arrays and the information regarding them to a binary file.
My first approach was to call fwrite 4 times: once for general information regarding the array, once for the timestamp, once for the dimension of the array and once to write the array itself.
This approach worked as it is quite simple, but the execution times were too slow, seeing as the program is multithreaded and it writes to a SAS drive frequently, flooding the drive with requests which presented a bottleneck.
The new approach was to create an array of structs containing the information needed, my struct would be as follows:
struct array_data{
int information;
int timestamp;
int size;
int* data_array;
}
During execution I would write the data to a buffer and when I had everything I need it would call a malloc to allocate array_data.data_array and copy everything from the buffer from inside a for loop.
The issue is when I call fwrite to write the whole struct, the first 3 members of the struct are written correctly, while the array is not and that is due to the address of the array not being contiguous, since it points to another place in memory after the malloc.
The best solution to this would be to declare the data_array as a static array, this way the fwrite would work as I need it to, but then I would have to call fwrite for every struct, instead of calling it once to write an array of structs, which would impact the performance, negating the use of the struct.
I've also tried using an array of dynamically allocated structs, by declaring my struct as follows:
struct array_data{
int information;
int timestamp;
int size;
int data_array[];
}
and allocating the array of structs using malloc, but the address of struct_array[1].information is not the one right after the struct_array[0].data_array[last_index], there seems to be another 5 bytes in between, so if I were to call fwrite with struct_array the data in the file would still be incorrect.
Is there a way to use structs to solve this issue or should I just stick with writing my arrays to the file as I did in the first place?
The following example creates, writes and reads your data. It is just a outline. Error checks on malloc, fread and fwrite ommitted:
#define N_DATA 10
#define N_INTS 5
struct array_data{
int information;
int timestamp;
int size;
int* data_array;
};
struct array_data arr[N_DATA];
void makeData(void){
int i;
for (i=0;i<N_DATA;i++) {
arr[i].data_array=malloc(N_INTS*sizeof(int));
arr[i].size= N_INTS;
}
}
void writeData(FILE *fp_out)
{
int i;
for (i=0;i<N_DATA;i++) {
fwrite(&arr[i],sizeof(arr[i]),1,fp_out);
fwrite(arr[i].data_array,arr[i].size*sizeof(int),1,fp_out);
}
}
void readData(FILE *fp_in)
{
int i= 0;
while(fread(&arr[i],sizeof(arr[i]),1,fp_in)==1) {
arr[i].data_array=malloc(arr[i].size*sizeof(int));
fread(arr[i].data_array,arr[i].size*sizeof(int),1,fp_in);
i++;
}
}
Related
I am trying to read a structure which contains another structure and then write it in a binary file. However, when i check if the structure was well read from the keyboard, the structure FIRMA is not read correctly. The value of 'nrang' is always 0 and the 'localitate' string is something very odd.
This is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char localitate[10];
int nrang;
} FIRMA;
typedef struct
{
char nume[20];
int varsta;
FIRMA firma;
} ANG;
int main()
{
FILE* f;
ANG* a;
int n,i;
if ((f=fopen("fis.txt","wb"))==NULL) exit(1);
printf("number?\n");
scanf("%d",&n);
a=(ANG*)malloc(n*sizeof(ANG*));
printf ("Dati valorile");
for (i=0; i<n; i++)
{
scanf("%s%d",&a[i].nume,&a[i].varsta);
scanf("%s",&a[i].firma.localitate);
scanf("%d",&a[i].firma.nrang);
fwrite(&a[i],sizeof(a[0]),1,f);
printf("%s\n%d\n%s\n%d\n",a[i].nume,a[i].varsta,a[i].firma.localitate,a[i].firma.nrang);
}
}
Note that sizeof(ANG*) is not the same as sizeof(ANG) (the former is the size of the pointer -- probably 8 -- whereas the latter is the size of the structure -- probably 40), which means you're only allocating about 1/5 of the memory you intend to. As a result, the later code winds up writing and reading past the end of what's been allocated, which has undefined behavior.
One practice that helps people with this is to get into the habit of using sizeof(*ptr) when allocating for a pointer ptr, which will always give you the size of what it points to so you don't have to think of "do I need sizeof(ANG) or sizeof(ANG*) here?". This is particularly useful when allocating multi-dimensional arrays (e.g. int ***three_d_array = malloc(n * sizeof(*three_d_array))).
I am working on a little project where I am trying to emulate a CPU declaring and assigning values to variables, so far so good. So I defined the following structures for my CPU and Memory.
CPU (Can only keep track of 3 variables)
typedef struct variableReference{
char *tag;
void *reference;
}variableReference;
typedef struct CPU{
int variableCounter;
int instructionPointer;
variableReference dataDictionary[3];
void *currentContext;
}CPU;
Memory (and it's creation function). By the way, CPU.currentContext points to the memory.base on startup, then it can change.
typedef struct Memory{
void *base;
int size;
}Memory;
Memory memory_create(int size){
Memory newMemory;
newMemory.base = malloc(size);
newMemory.size = size;
return newMemory;
}
So the first thing I do is allocate a block of memory and keep track of it using the CPU current context pointer. I already have a function that asks the cpu to declare a variable (variables can only be integer) and another one that asks the cpu to assign that variable a value (int). To do this, I keep track of a limited amount of variable names and references in cpu.dataDictionary.
The variable declaring seems to work just fine, but the problem occurs when I try to assign that variable a value, which I do like this (e.g. a = 4;):
cpu_assignVariable(&myCPU,"a",4,&myMemory);
At that time, in my cpu.dataDictionary I have this in the first record {"a",0x804b008}, so all I should have to do is look for that position in the allocated memory block, and copy the value (integer 4), like this:
void *reference = cpu_dereferenceVariable(*myCPU,tag); // gets a's address
memory_write(reference,1,sizeof(value),(void *) value); // writes the value
now the memory_write implementation, where I get the Segmentation Fault (I have an offset of 1 because on the "reference" position I previously wrote the variable name:
int memory_write(void *base, int offset,int size,void *value){
memcpy(base+offset,value,size);
return 0;
}
I'd expect the memory block to look like this |a|0|0|0|4|x|x|...|x|, but all I get is a segmentation fault error. Any ideas???
Thanks in Advance!
In the following function, I am parsing string form a linked list and giving values to struct array. Is there any way that let me not use mallocs inside while loop.I can not handle glibc errors, so looking for other way.I tried to use char arrays instead of char* for the struct fields. But I am getting seg error. Actually the function is working, but I ahve to call the function 15000 times later, so I want to make sure it won't cause any memory trouble that time.
struct CoordNode
{
int resNum;
double coordX;
double coordY;
double coordZ;
char atomName[4];
};
void parseCrdList()
{
int resNum=1;
int tAtomNum,i;
char *tcoordX, *tcoordY, *tcoordZ, *tatomName, tresNum[5];
ccur_node=headCoord_node->next;
struct CoordNode *t;
t=malloc(numofRes*sizeof(struct CoordNode));
i=0;
while (ccur_node!=NULL)
{
tresNum=malloc(5*sizeof(char));
memcpy(tresNum,ccur_node->crdRow+26,4);
resNum=atoi(tresNum);
t[i].resNum=resNum;
tcoordX=malloc(8*sizeof(char));
memcpy(tcoordX,ccur_node->crdRow+35,7);
tcoordY=malloc(8*sizeof(char));
memcpy(tcoordY,ccur_node->crdRow+43,7);
tcoordZ=malloc(8*sizeof(char));
memcpy(tcoordZ,ccur_node->crdRow+51,7);
t[i].coordX=strtod(tcoordX,NULL);
t[i].coordY=strtod(tcoordY,NULL);
t[i].coordZ=strtod(tcoordZ,NULL);
tatomName=malloc(4*sizeof(char));
memcpy(tatomName,ccur_node->crdRow+17,3);
strcpy(t[i].atomName,tatomName);
old_ccur_node=ccur_node;
ccur_node=ccur_node->next;
//free(old_ccur_node);
i++;
}
numofRes=i;
addCoordData(t);
//free(t);
t=NULL;
}
A couple of thoughts and guesses.
First, as I mentioned before, sizeof(char) is always 1 byte in C, it's actually standard byte definition in C. So remove those as completely unnecessary and hard to read.
Back to the main problem.
You never use array of chars bigger than 8, so just make it statically 8 bytes long. If you have to call you function 15k times, that will save you tons of time(malloc takes time to allocate memory for you).
Given information from the question I guess your segfault was the cause of not initialising memory you allocated with malloc or reserved for auto char [8] with its declaration
1. You allocate (or 2nd version - declare 8-byte array) 8 bytes. It works fine. But you get 8 bytes full of trash here.
2. You copy 7 bytes from your list. And that's fine, too. But you forget to NULL terminate, so if you try to print it out back, you get segfault.EDIT If it works then probably you got lucky, because it shouldn't.
Solution
Replace char * witch char [8], remove all mallocs and frees corresponding to those char *, null terminate all your char[8] after strcpy, strncpy, or memcpy (whatever your choice is, depending on how confident you are that your data in list is correct) data to them.
Check your code with valgrind before further use, too.
It's surprising you saying this function worked for you. From what I see from your code I had a lot of memory leaks to begin with because non of those 8-byte mallocs was ever fried.
The second thing is that it looks like you're allocating array of CoordNode before knowing the actual number of data records to parse. I added proper numofRes calculation before allocation.
Since you don't modify input data you don't actually need all those mallocs and memcpy's, you can use crdRow in strtod() immediatly, assuming it has char * type.
The last thing: it's generally a bad practice to do allocation in one place and freeing data in another. So it's better you free your headCoord_node structure in a place where it was allocated, after parsing it. The decision of freeing t depends on how addCoordData(t) treats its parameter.
void parseCrdList()
{
struct CoordNode *t;
int i;
// count number of records to parse
numofRes = 0;
ccur_node = headCoord_node->next;
while (ccur_node != NULL)
{
numofRes++;
ccur_node=ccur_node->next;
}
t=malloc(numofRes*sizeof(struct CoordNode));
i=0;
ccur_node = headCoord_node->next;
while (ccur_node!=NULL)
{
t[i].resNum=atoi(ccur_node->crdRow+26);
t[i].coordX=strtod(ccur_node->crdRow+35,NULL);
t[i].coordY=strtod(ccur_node->crdRow+43,NULL);
t[i].coordZ=strtod(ccur_node->crdRow+51,NULL);
strncpy(t[i].atomName,ccur_node->crdRow+17,4);
ccur_node=ccur_node->next;
i++;
}
numofRes=i;
addCoordData(t);
//free(t); // <<< it depends on how addCoordData treats t
}
i am new to C so i believe there is a rookie mistake somewhere in my code due to lack of fundamentals in pointers and memory allocation.
I have a binary file representing numerical data, and i am trying to read and store that data.
This is first part of the code that opens the file, reads fisrt few numbers in file which are than used to allocate enough memory for the struct emxArray_real_T.
Struct:
struct emxArray_real_T
{
real_T *data;
int32_T *size;
int32_T allocatedSize;
int32_T numDimensions;
boolean_T canFreeData;
}
First part of main:
# include <stdio.h>
# include <stdlib.h> /*atoi*/
# include <assert.h>
int main(int argc, char** argv){
//Variable declaration
unsigned short numOfSums;
unsigned long chSum, countRSN, countPeriods;
int i,j;
FILE *file;
//Open file
file = fopen("testBin.bin","rb");
//Read first number that tells how many items to skip
fread(&numOfSums, 2, 1,file);
//Skip that many items
for (i=0;i<numOfSums;i++){
fread(&chSum,4,1,file);
}
//Read next two numbers
fread(&countRSN,4,1,file);
fread(&countPeriods,4,1,file);
//Allocate enaugh space based on the size of countRSN and countPeriods
struct emxArray_real_T* Sa_1 = malloc(sizeof(*Sa_1)*1);
assert(Sa_1 != NULL);
Sa_1->data=malloc(sizeof(real_T)*countRSN*countPeriods);
Sa_1->size=malloc(sizeof(int32_T)*2);
Sa_1->allocatedSize=(sizeof(int32_T)*1);
Sa_1->size[0]=countRSN;
Sa_1->size[1]=countPeriods;
struct emxArray_real_T *Sa_2;
Sa_2=(struct emxArray_real_T*)malloc(sizeof(struct emxArray_real_T)*1);
assert(Sa_2 != NULL);
Sa_2->data=(real_T*)malloc(sizeof(real_T)*countRSN*countPeriods);
Sa_2->size=malloc(sizeof(int32_T)*2);
Sa_2->allocatedSize=(sizeof(int32_T)*1);
Sa_2->size[0]=countRSN;
Sa_2->size[1]=countPeriods;
struct emxArray_real_T *sVs30;
sVs30=(struct emxArray_real_T*)malloc(sizeof(struct emxArray_real_T));
sVs30->data=malloc(sizeof(real_T)*countRSN);
sVs30->size=malloc(sizeof(int32_T)*1);
sVs30->allocatedSize=(sizeof(int32_T)*1);
sVs30->size[0]=countRSN;
Here is the problem. If i try to store my data and transpose it, because it's not in the right order, i get Segmentation fault,
for (i=0;i<countRSN;i++){
for (j=0;j<countPeriods;j++){
fread(&Sa_1->data[countRSN*j+i],8,1,file);
}
}
if i just try like this, it is working:
for (i=0;i<countRSN*countPeriods;i++){
fread(&Sa_1->data[i],8,1,file);
}
.
.
.
fclose(file);
free(Sa_1);
free(Sa_2);
free(sVs30);
return 0;
}
You are assuming size of types. Use sizeof everywhere you use 4, 2, 8 etc. Also make sure the fread will work with short int, which I doubt
With every call to fread you read 8 bytes and write them to the array. It seems to me you are storing them in the correct position. A Segmentation fault would have to be expected if sizeof(real_T) is smaller than 8.
If sizeof(real_T) is smaller than 8, say it's size 4*, &Sa_1->data[countRSN*countPeriods-1] will write 4 of the 4 bytes in a valid location, and the other 4 bytes will be written outside of the allocated range.
Why does the code crash in one case and not the other? First, by accessing unallocated memory you are in the territory of undefined behaviour. The program doesn't need to behave in a well defined way anymore. Second, fread doesn't write to the buffer if the file stream has already reached the end. The code which works in your example only writes to the last address if the file is long enough.
*In Matlab, real_T is either 4 or 8 bytes, depending on defines. If it's 4 bytes, the code given by the op should throw a segfault.
struct emxArray_real_T* Sa_1 = malloc(sizeof(*Sa_1)*1);
To
struct emxArray_real_T* Sa_1 = malloc(sizeof(struct emxArray_real_T));
I am writing a light weight serialization function and need to include two variable sized arrays within this.
How should I track the size of each?
How should I define the struct?
Am I going about this all wrong?
EDIT: the result must be a contiguous block of memory
This resolves to something like
typedef struct
{
size_t arr_size_1, arr_size_2;
char arr_1[0/*arr_size_1 + arr_size_2*/];
} ...;
The size(s) should be in the front of the dynamic sized data, so that it doesn't move when expanding your array.
You cannot have 2 unknown sized arrays in your struct, so you must collapse them into one and then access the data relative from the first pointer.
typedef struct MyStruct_s
{
int variable_one_size;
void* variable_one_buf;
int variable_two_size;
void* variable_two_buf;
} MyStruct;
MyStruct* CreateMyStruct (int size_one, int size_two)
{
MyStruct* s = (MyStruct*)malloc (sizeof (MyStruct));
s->variable_one_size = size_one;
s->variable_one_buf = malloc (size_one);
s->variable_two_size = size_two;
s->variable_two_buf = malloc (size_two);
}
void FreeMyStruct (MyStruct* s)
{
free (s->variable_one_buf);
free (s->variable_two_buf);
free (s);
}
Since the data should be continuous in memory it is necessary to malloc a chunk of memory of the right size and manage it's contents more or less manually. You probably best create a struct that contains the "static" information and related management functions that do the memory management and give access to the "dynamic" members of the struct:
typedef struct _serial {
size_t sz_a;
size_t sz_b;
char data[1]; // "dummy" array as pointer to space at end of the struct
} serial;
serial* malloc_serial(size_t a, size_t b) {
serial *result;
// malloc more memory than just sizeof(serial), so that there
// is enough space "in" the data member for both of the variable arrays
result = malloc(sizeof(serial) - 1 + a + b);
if (result) {
result->sz_a = a;
result->sz_b = b;
}
return result;
}
// access the "arrays" in the struct:
char* access_a(serial *s) {
return &s->data[0];
}
char* access_b(serial *s) {
return &s->data[s->sz_a];
}
Then you could do things like this:
serial *s = ...;
memcpy(access_a(s), "hallo", 6);
access_a(s)[1] = 'e';
Also note that you can't just assign one serial to another one, you need to make sure that the sizes are compatible and copy the data manually.
In order to serialize variably-sized data, you have to have a boundary tag of some sort. The boundary tag can be either a size written right before the data, or it can be a special value that is not allowed to appear in the data stream and is written right after the data.
Which you choose depends on how much data you are storing, and if you are optimizing for size in the output stream. It is often easier to store a size before-hand, because you know how big to make the receiving buffer. If you don't then you have to gradually resize your buffer on load.
In some ways, I'd do things like Dan Olson. However:
1) I'd create the final struct by having two instances of a simpler struct that has just one variable array.
2) I'd declare the array with byte* and use size_t for its length.
Having said this, I'm still not entirely clear on what you're trying to do.
edit
If you want it contiguous in memory, just define a struct with two lengths. Then allocate a block big enough for both blocks that you want to pass, plus the struct itself. Set the two lengths and copy the two blocks immediately after. I think it should be clear how the lengths suffice to make the struct self-describing.