I'm making a program in C, and I'mm having some troubles with memory, I think.
So my problem is: I have 2 functions that return a struct. When I run only one function at a time I have no problem whatsoever. But when I run one after the other I always get an error when writting to the second struct.
Function struct item* ReadFileBIN(char *name) -- reads a binary file.
struct tables* getMesasInfo(char* Filename) -- reads a text file.
My code is this:
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int numberOfTables=0;
int numberOfItems=0;
//struct tables* mesas;
//struct item* Menu;
typedef struct item{
char nome[100];
int id;
float preco;
};
typedef struct tables{
int id;
int capacity;
bool inUse;
};
struct tables* getMesasInfo(char* Filename){
struct tables* mesas;
char *c;
int counter,numberOflines=0,temp=0;
char *filename=Filename;
FILE * G;
G = fopen(filename,"r");
if (G==NULL){
printf("Cannot open file.\n");
}
else{
while (!feof(G)){
fscanf(G, "%s", &c);
numberOflines++;
}
fclose(G);
}
/* Memory allocate for input array */
mesas = (struct tables *)malloc(numberOflines* sizeof(struct tables*));
counter=0;
G=fopen(filename,"r");
while (!feof(G)){
mesas[counter].id=counter;
fscanf(G, "%d", &mesas[counter].capacity);
mesas[counter].inUse= false;
counter++;
}
fclose(G);
numberOfTables = counter;
return mesas;
}
struct item* ReadFileBIN(char *name)
{
int total=0;
int counter;
FILE *ptr_myfile;
struct item my_record;
struct item* Menu;
ptr_myfile=fopen(name,"r");
if (!ptr_myfile)
{
printf("Unable to open file!");
}
while (!feof(ptr_myfile)){
fread(&my_record,sizeof(struct item),1,ptr_myfile);
total=total+1;
}
numberOfItems=total-1;
Menu = (struct item *)calloc(numberOfItems , sizeof(struct item));
fseek(ptr_myfile, sizeof(struct item), SEEK_END);
rewind(ptr_myfile);
for ( counter=1; counter < total ; counter++)
{
fread(&my_record,sizeof(struct item),1,ptr_myfile);
Menu[counter] = my_record;
printf("Nome: %s\n",Menu[counter].nome);
printf("ID: %d\n",Menu[counter].id);
printf("Preco: %f\n",Menu[counter].preco);
}
fclose(ptr_myfile);
return Menu;
}
int _tmain(int argc, _TCHAR* argv[])
{
struct item* tt = ReadFileBIN("menu.dat");
struct tables* t = getMesasInfo("Capacity.txt");
getchar();
}**
the error that im getting is :
"Unhandled exception at 0x00411700 in test.exe: 0xC0000005: Access violation writing location 0x00000000."
in "Menu[counter] = my_record;"
Thanks in advance.
You seem to allocate a memory block of the wrong size in getMesasInfo(): sizeof(struct tables*) gives you the size of the pointer, not that of the struct it is pointing to:
mesas = (struct tables *)malloc(numberOflines* sizeof(struct tables*));
So you can easily overwrite unallocated memory. The proper allocation should be
mesas = (struct tables *)malloc(numberOflines* sizeof(struct tables));
or, similar to how you allocate the other array in ReadFileBIN():
mesas = (struct tables *)calloc(numberOflines, sizeof(struct tables));
Moreover, I don't know whether it's intentional or not, but in ReadFileBIN() you are allocating (1) and reading (2) one less record than the total number of records:
numberOfItems=total-1; // 1
Menu = (struct item *)calloc(numberOfItems , sizeof(struct item)); // 1
fseek(ptr_myfile, sizeof(struct item), SEEK_END);
rewind(ptr_myfile);
for ( counter=1; counter < total ; counter++) // 2
...
Since the loop counter is started from 1 (instead of 0 as is normal in C), you effectively execute the loop total-1 times. That is, you read into elements 1 to total-1 of the array. However, the real elements of the array are indexed from 0 to total-2 so the very first element in the array is left uninitialized, and in the end you commit a buffer overflow error.
You have a problem in these lines:
numberOfItems=total-1;
Menu = (struct item *)calloc(numberOfItems , sizeof(struct item));
fseek(ptr_myfile, sizeof(struct item), SEEK_END);
rewind(ptr_myfile);
for ( counter=1; counter < total ; counter++)
First, you're setting numberOfItems to one less than the total. This is incorrect. You don't even need numberOfItems; since total has the number of lines in the file, the next line should really be Menu = (struct item*) calloc(total, sizeof(struct item));
Second, you're trying to use Menu as a one-based array in the for loop. C arrays are zero-based. You should have the for loop use for (counter = 0; counter < total; counter++).
Finally, as Peter pointed out, in the first function you're allocating the wrong size of object. You need to malloc numberOfLines*(sizeof(struct tables) (not sizeof(struct tables*).
To further illustrate Peter's point:
struct tables {
int id;
int capacity;
int inUse; /* bool is not a C type */
};
int main()
{
printf("sizeof: %d\n",sizeof(struct tables*));
printf("sizeof: %d\n",sizeof(struct tables));
}
Will output:
sizeof: 4
sizeof: 12
Related
Hello i am slowly learning c and trying my best.
Can someone tell me why my variables are undefined?
"processId, userId, arrivalTime, priority, expectedTimeRemaining, expectedPctCPU, realTime" are all giving an error!
Please help, i provided my code. I tried reading up about structures and pointers. Followed resources, and now i am trying to implement it myself.
Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#define _CRT_SECURE_NO_WARNINGS
typedef enum States { NEW, READY, RUNNING, BLOCKED, SUSPENDED, EXIT, SUSPEND_READY } State;
char stateNames[7][14] = { "New", "Ready", "Running", "Blocked", "Suspended", "Exit", "SuspendReady" };
// partial - skips info needed to actually conduct process switch - contents of registers, program counter, stack pointers, ... pointers to page tables ...
// we ARE going to need some way of indicating IO needs so can decide when they should block
struct processblock {
int processId;
int userId; // pointer instead?
State processState; // Not input - initially NEW
int arrivalTime; // time units in simulation, not actual time
int priority; // base priority
int currentPriority; // can be upped or lowered based on what has happened with the process - not input - initially same as base priority
int timeWaitingSoFar; // Not input - initially zero
int timeProcessingLastRun; // Not input - initially zero
int timeProcessingSoFar; // Not input - initially zero
int expectedTimeRemaining;
struct event* waitingOn; // ??? // Not input - initially zero
int expectedMemoryNeed;
int expectedPctCPU; // to get an idea of whether CPU bound or IO bound
bool realTime; // whether a real-time process or not (real-time processes may need immediate attention)
struct processblock* nextPtr; // not used in this program - but preparing for linked list version
};
//fill in the array from file
int fillArrayFromFile(struct processblock processor[], FILE*fPtr, int maxSize) {
int count = 0;
//unsure if realtime is a parameter, pls check and confirm with me
while ((count < maxSize) && fscanf("fPtr,%d,%d,%d,%d,%d,%d,%d", processId, userId, arrivalTime, priority, expectedTimeRemaining, expectedPctCPU, realTime) != EOF) {
//fill in each part of the array
processor[count].processId = count;
}
}
You should use a linked list to store the data you need, here there is an example, this code reads the lines of a file named test.txt that has this layout:
100,101,20,1,50,1,0
102,105,30,1,55,1,1
101,10,40,0,56,1,1
and store all the values in a linked list, that contains your structure. I hope you'll learn something new, happy coding!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define _CRT_SECURE_NO_WARNINGS
typedef enum States { NEW, READY, RUNNING, BLOCKED, SUSPENDED, EXIT, SUSPEND_READY } State;
char * stateNames[7] = { "New", "Ready", "Running", "Blocked", "Suspended", "Exit", "SuspendReady" };
struct processblock {
int processId;
int userId;
int arrivalTime;
int priority;
int expectedTimeRemaining;
int expectedPctCPU;
int realTime; // scanf can't read boolean
State processState;
int currentPriority;
int timeWaitingSoFar;
int timeProcessingLastRun;
int timeProcessingSoFar;
int expectedMemoryNeed;
};
struct Node
{
struct processblock pblock;
struct Node *next;
};
typedef struct Node * List;
void NewNode(List * p , struct processblock pb) //function that creates new linked list nodes
{
List temp;
temp = (List)malloc(sizeof(struct Node));
temp->pblock = pb;
temp->next = *p;
*p = temp;
}
int fillArrayFromFile(char *filename, List * p) {
FILE *fPtr;
int count = 0;
struct processblock pb;
char * buffer;
buffer = malloc(sizeof(struct processblock));
if(!(fPtr= fopen(filename, "r")))
{
perror("No File");
fclose(fPtr);
return 0;
}
while(fgets(buffer,sizeof(struct processblock),fPtr))//read every line of file and store them in a buffer
{
if(sscanf(buffer,"%d,%d,%d,%d,%d,%d,%d", &pb.processId, &pb.userId, &pb.arrivalTime, &pb.priority, &pb.expectedTimeRemaining, &pb.expectedPctCPU, &pb.realTime) == 7 ) // read from the buffer
{
NewNode(p, pb); // creates new node from filled structure
count++;
}
}
free(buffer);
fclose(fPtr);
return count;
}
void ViewElements(List p)
{
struct processblock pb;
while(p != NULL)
{
pb = p->pblock;
printf("%d,%d,%d,%d,%d,%d,%d\n", pb.processId, pb.userId, pb.arrivalTime, pb.priority, pb.expectedTimeRemaining, pb.expectedPctCPU, pb.realTime);
p = p->next;
}
}
int main()
{
List HeadNode = NULL;
printf("Loaded %d lines\n", fillArrayFromFile("test.txt", &HeadNode));
ViewElements(HeadNode);
return 0;
}
Below is my (incomplete) code for a merge sort project. This worked fine for the parts I have implemented until I switched from the 128 line test file to the 31 mb file that is supposed to be sorted. Now getting a segfault and I'm not sure what to do in order to solve this.
Removed some lines I believe are inconsequential because "mostly code".
struct Record {
char key[KEYSIZE+1];
char data[DATASIZE+1];
};
int threadCount;
int tiers;
static struct ThdArg {
int thdNum; // Thread number 0,1,2,3
struct Record * lowRec; // First record of group or first index of record
struct Record * hiRec; // Last record of group or last index of record
};
int lines;
int tiers;
void *threadFunc(void *var)
{
struct ThdArg temp2 = *((struct ThdArg*)var);
qsort((temp2.lowRec), lines/threadCount, sizeof(struct Record), comparator);
for(int k=0;k<tiers;k++)
if(temp2.thdNum%(int)(pow(2,k+1))==0)
{
qsort((temp2.lowRec), lines/(threadCount/(int)pow(2,k+1)), sizeof(struct Record),comparator);
}
}
int main(int argc, char **argv[])
{
if (argc!=2)
{
printf("Please enter a file name");
return 0;
}
threadCount =8;
tiers =(int)log2((double)threadCount);
pthread_t threads[threadCount];
FILE *recordFile=fopen(argv[1], "r");
char ch;
fseek(recordFile, 0, SEEK_END);
lines = ftell(recordFile);
fseek(recordFile, 0, SEEK_SET);
lines=lines/64;
struct Record recArr[lines];
char buffer[9];
char buffer2[57];
for(int j=0;j<lines;j++)
{
fgets(buffer, 9, recordFile);
for(int i=0;i<8;i++)
{
recArr[j].key[i]=buffer[i];
}
recArr[j].key[8]='\0';
fgets(buffer2, 57, recordFile);
for(int i=0;i<56;i++)
{
recArr[j].data[i]=buffer2[i];
}
recArr[j].data[57]='\0';
}
struct ThdArg temp[threadCount];
for(int i=0;i<threadCount;i++)
{
temp[i].thdNum = i;
temp[i].lowRec=&recArr[(lines/threadCount)*i];
temp[i].hiRec=&recArr[(lines/threadCount)*(i+1)-1];
pthread_create(&threads[i],NULL, threadFunc, (void *)&temp[i]);
}
for(int i=0;i<threadCount;i++)
{
pthread_join(threads[i], NULL);
}
}
The following line:
struct Record recArr[lines];
allocates memory on the stack. Its size is restricted.
If you read a file which can be be very big use malloc:
#include <stdlib.h>
typedef struct {
char key[KEYSIZE +1];
char data[DATASIZE +1];
}Record;
...
recArr = malloc(sizeof(Record) * lines);
...
free(recArr);
You can use the pointer like an array. (In fact, they are the same)
I'm trying to write a C program that gathers all structures passing a specific condition into an array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Book {
char title[20];
unsigned int published;
char authors[50];
unsigned int pages;
};
unsigned int get_books_from(unsigned int year, int length, struct Book data[], struct Book results[]);
int main(int argc, char* argv[]) {
struct Book data[5];
// Init book pool inside data
struct Book books[0];
unsigned int books_count = get_books_from(1973, 5, data, books);
return 0;
}
unsigned int get_books_from(unsigned int year, int length, struct Book data[], struct Book results[]) {
results = (struct Book*) malloc(sizeof(struct Book));
unsigned int results_count = 0;
int i;
for (i = 0; i < length; i++) {
if (data[i].published == year) {
*(results + results_count) = data[i];
results = (struct Book*) realloc(results, (++results_count + 1) * sizeof(struct Book));
}
}
return results_count;
}
The logic seems to be working fine, however when trying to access the books array contents outside of the get_books_from function (where it's called results), all the data becomes corrupted. Some of the original data is still there but not in the right places, it looks as if the data got shifted. I checked the pointers to both books and results and it appears that those variables do not point to the same place in memory after the function finishes. What could be the problem?
Your get_books_from changes the value of results here:
results = (struct Book*) realloc(results, (++results_count + 1) * sizeof(struct Book));
But it provides no way for the caller to get the new value of results.
Worse, you call get_books_from with data, which was allocated on the stack in main. You can't realloc it. As the documentation for realloc says, the pointer you are attempting to reallocate must been returned by a previous call to malloc, calloc, or realloc. Fortunately, you ignore that value. But that renders the struct Book data[5]; in main incomprehensible. Why allocate space on the stack?
In addition to the other answer:
You probably want something like this (untested, non error checking code, declarations and #includes ommited for brevity):
unsigned int get_books_from(unsigned int year, int length, struct Book data[], struct Book **results);
int main(int argc, char* argv[]) {
struct Book data[5];
// Init book pool inside data
struct Book *books;
unsigned int books_count = get_books_from(1973, 5, data, &books);
return 0;
}
unsigned int get_books_from(unsigned int year, int length, struct Book data[], struct Book **results) {
*results = (struct Book*) malloc(sizeof(struct Book));
unsigned int results_count = 0;
int i;
for (i = 0; i < length; i++) {
if (data[i].published == year) {
*(*results + results_count) = data[i];
*results = (struct Book*) realloc(*results, (++results_count + 1) * sizeof(struct Book));
}
}
return results_count;
}
I have a struct with an array of another struct inside it and I am having trouble initialising the struct.
typedef struct stack * Stack;
typedef struct book * Book;
struct book {
char *title;
int pages;
};
struct stack {
int num_books;
Book array[50]
};
What I am trying to do is to create an empty stack with zero books but I keep getting segmentation faults on everything I tried.
Here is my initialization function:
Stack create_stack(void) {
Stack s = malloc(sizeof(struct stack) * 50);
s->num_books = 0;
// s->array[0]->title = Null;
// s->array[0]->pages = 0;
// the above 2 lines give a seg fault: 11
// I also tried:
// s->array = s->array = malloc(sizeof(struct book) * 50);
// Which gives the error that array type 'Book [50]' is not assignable
return s;
}
How can I create an empty stack with zero books?
You haven't allocated memory for struct book objects. The struct:
struct stack {
int num_books;
Book array[50];
};
defines array member as 50 elements array of pointers to book struct (that is, Book is synonym to struct book *). These are still "wild" pointers, and you need to assign them with allocated struct objects. In other words, by calling:
Stack s = malloc(sizeof(struct stack) * 50);
you have made a room for fifty objects of type struct stack, but inside each of these structs, there is room for struct book pointers, not objects itself.
Like mentioned in comments, typedefing a pointer type is an easy way to obfuscate the code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 2
typedef struct book {
char * title ;
int pages;
} Book;
typedef struct stack {
int num_book;
Book book_arr[SIZE];
} Stack;
//------------------------------------------------
int main (void ){
Stack s1;
printf("Enter Number of Books : " );
scanf("%d",&s1.num_book);
getchar();
//BOOK
for( size_t j = 0 ; j < s1.num_book ; j++ ){
char temp[100];
printf("Enter the Book Title for %zd Book : ", (j+1) );
fgets(temp,100,stdin);
strtok(temp,"\n"); // for removing new line character
s1.book_arr[j].title = malloc ( sizeof(temp) +1 );
strcpy(s1.book_arr[j].title,temp);
// puts(s1.book_arr[j].title );
printf("Enter Pages for %zd Book : ",(j+1) );
scanf("%d",&s1.book_arr[j].pages); getchar();
}
//PRINT
size_t count = 0 ;
for( size_t i = 0 ; i < s1.num_book ; i++ ){
while(count < SIZE ) {
printf("Book Title : %s\nBook pages : %d\n",s1.book_arr[count].title, s1.book_arr[count].pages );
free(s1.book_arr[count].title );
count++;
}
}
return 0;
}
Is that what you were trying to achieve ?
I have a bit of a problem. I am barely starting out with C, (comming from a C# background) and I am having problem with double pointers.
I have a structure as follows:
#ifndef __PROCESSINFO_H
#define __PROCESSINFO_H
struct ProcessInfo
{
int ProcesId;
int Priority;
int ExecutionTime;
int EllapsedTime;
char* ProcessName;
};
struct ProcessInfo *ProcessInfo_Allocate(int processId, char *processName, int priority, int executionTime);
void ProcessInfo_ToString(struct ProcessInfo *processInfo);
void ProcessInfo_Dispose(struct ProcessInfo *processInfo);
#endif
Implementation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "processinfo.h"
struct ProcessInfo *ProcessInfo_Allocate(int processId, char *processName, int priority, int executionTime)
{
struct ProcessInfo *processInfo;
processInfo = (struct ProcessInfo *)malloc(sizeof(struct ProcessInfo));
processInfo->ProcessId = processId;
processInfo->ProcessName = processName;
processInfo->Priority = priority;
processInfo->ExecutionTime = executionTime;
processInfo->EllapsedTime = 0;
return processInfo;
}
void ProcessInfo_ToString(struct ProcessInfo *processInfo)
{
printf(" %6i %6i %10i %10i, %25s", processInfo->ProcessId, processInfo->Priority, processInfo->ExecutionTime, processInfo->EllapsedTime, processInfo->ProcessName);
}
void ProcessInfo_Dispose(struct ProcessInfo *processInfo)
{
if(processInfo != NULL)
{
if(processInfo->ProcessName != NULL)
{
free(processInfo->ProcessName);
}
free(processInfo);
}
}
so now I have to manage a whole lot of ProcessInfo instances. I wrote another structure which would hold a pointer to a pointer to the ProcessInfo sturcture because i thought that I can increase and decrease it in size as needed (without too much hassle);
#ifndef __SCHEDULER_H
#define __SCHEDULER_H
struct Scheduler
{
struct ProcessInfo** Processes;
};
struct Scheduler* Scheduler_Allocate(void);
#endif
So the question is how do I initialize the **Processes member inside the Scheduler_Allocate method? How do I add stuff to it?
struct Scheduler s;
s.Processes = malloc(sizeof(struct ProcessInfo*) * size);
s.Processes[0] = ProcessInfo_Allocate(...);
// Add more items:
s.Processes = realloc(malloc(sizeof(struct ProcessInfo*) * (size + 1));
s.Processes[size] = ProcessInfo_Allocate(...);
size++;
Also see my example here:
Array of C structs
You don't need a double pointer to increase/decrease the size. Just use a normal pointer and realloc.
struct ProcessInfo* processes = malloc(sizeof(struct ProcessInfo) * 2);
struct ProcessInfo* processes_tmp;
if (!processes) {
/* bail */
}
/* do whatever with processes[0] and [1] */
processes_tmp = processes;
processes = realloc(processes, sizeof(struct ProcessInfo) * 5);
if (!processes) {
free(processes_tmp);
/* bail */
}
/* processes[0] and [1] are unchanged, and [2] [3] and [4] are now valid */
Then instead of having a ProcessInfo_Allocate, you could create a ProcessInfo_Init that would do most of the same except not allocating the memory:
int ProcessInfo_Init(struct ProcessInfo *pi, int processId, char *processName, int priority, int executionTime)
{
if (!pi) {
return -1;
}
pi->ProcessId = processId;
pi->ProcessName = processName;
pi->Priority = priority;
pi->ExecutionTime = executionTime;
pi->EllapsedTime = 0;
return 0;
}
size_t size = 10;//or what ever is the number of processes
struct ProcessInfo * process = (struct ProcessInfo *)malloc(size * sizeof(struct ProcessInfo));
if(!process)
//perhaps stop program? Do something
Processes = &process;
//later on
int i;
for(i = 0; i < size; i++)
{
printf("Process id =%d",Processes[i]->ProcesId);
etc
}
Pointer to pointer is initialized as array of pointers. So call malloc(count * sizeof(ProcessInfo*)) to initialize it. This way you get array of pointers to ProcessInfo. Then call malloc(sizeof(ProcessInfo)) many times to create particular ProcessInfo structures and put pointers to them to the array.
Also, user470379 is right that you don't need pointer to pointer just to change number of items in your array. But your idea is actually not bad either, you can stay with it if you want.
Also, since you are familiar with C#, I would recommend you to start with writing something like ArrayList in C. Then you can use it in many situations (like this one).
First change your definition to:
typedef struct Scheduler {
struct ProcessInfo** Processes;
} Scheduler;
Then something like this:
Scheduler *s;
s = malloc(sizeof(Scheduler));
if (s == NULL) {
exit(-1);
}
s = memset(s, 0, sizeof(Scheduler));
/* Or enter your own memory allocation stuff here */
i = 0; /* Or use some other number */
s->Processes[i] = someProcessInfo;