C - pointer to array of pointers - c

i have to store the pointers of a data structure.
So, i need an array of pointer.
I created a simple example, but i receive a segmentation fault.
Why i cannot do
buf->data[i] = pkt ??
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define MAX_SIZE 500000
#define MAX_CHAR 1024
char *string = "HelloHelloHello";
struct pkt {
char *buf;
int seq;
};
struct buffer {
int a;
int b;
struct pkt **data;
};
struct buffer *new_buffer() {
struct buffer *new;
new = malloc(sizeof(struct buffer) * MAX_SIZE);
if (new == NULL) {
perror("malloc(buffer)");
exit(EXIT_FAILURE);
}
struct pkt *data;
data = malloc(sizeof(struct pkt) * MAX_SIZE);
if (data == NULL) {
perror("malloc(data)");
exit(EXIT_FAILURE);
}
new->data = &data;
new->a = 0;
new->b = 0;
return new;
}
struct pkt *new_pkt(char *data, int seq) {
struct pkt *pkt;
pkt = malloc(sizeof(struct pkt));
if (pkt == NULL) {
perror("malloc(pkt)");
exit(EXIT_FAILURE);
}
pkt->buf = malloc(sizeof(char) * MAX_CHAR);
if (pkt->buf == NULL) {
perror("malloc(pkt->buf)");
exit(EXIT_FAILURE);
}
strncpy(pkt->buf, data, MAX_CHAR);
pkt->seq = seq;
return pkt;
}
void add_pkt(struct pkt *pkt, struct buffer *buf, int i) {
buf->data[i] = pkt; //segmentation fault
}
int main() {
struct buffer *my_buffer = new_buffer();
struct pkt *pkt;
int i;
for(i=0; i<MAX_SIZE; ++i) {
pkt = new_pkt(string, i);
add_pkt(pkt, my_buffer, i);
printf("[%d]", i);
}
return 0;
}

change
struct pkt *data;
data = malloc(sizeof(struct pkt) * MAX_SIZE);
if (data == NULL) {
perror("malloc(data)");
exit(EXIT_FAILURE);
}
new->data = &data;
to
new->data = malloc(sizeof(struct pkt*) * MAX_SIZE);
if (new->data == NULL) {
perror("malloc(new->data)");
exit(EXIT_FAILURE);
}
struct pkt *data; is a local variable, saving its address and using it after the scope ends, is undefined behaviour. Also you want a memory area where you can save some struct pkt*s and not struct pkts.
Since you are not freeing anything, you have a big memory leak.

Related

Dynamic reallocation an array of structures with malloc and realloc

I am really having a difficult time trying to create an array of structures using malloc and realloc. I have posted mostly the entire code base, or at least the relevant information pertaining to the question below.
struct _section {
char *sectName;
int start_addr;
int end_addr;
char *bytes;
};
struct _section *get_exe_sections(struct _section *exe_sect, Elf *elf, GElf_Ehdr *ehdr, GElf_Shdr *shdr, Elf_Data *data) {
exe_sect->sectName = elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name);
exe_sect->start_addr = shdr->sh_addr;
exe_sect->end_addr = shdr->sh_addr + shdr->sh_size;
exe_sect->bytes = (unsigned char *)data->d_buf;
return exe_sect;
}
int main(int argc, char *argv[]) {
Elf *elf;
int fd;
//process input file
int sections_count = count_sections(elf);
GElf_Ehdr ehdr_mem;
GElf_Ehdr *ehdr = gelf_getehdr(elf, &ehdr_mem);
struct _section *exe_sect = (struct _section *)malloc(sizeof(struct _section));
for(int cnt = 0; cnt < sections_count; cnt++) {
Elf_Scn *scn = elf_getscn(elf, (size_t)cnt);
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr(scn, &shdr_mem);
Elf_Data *data = elf_getdata(scn, NULL);
if(ehdr == NULL || shdr == NULL)
exit(1);
if(strcmp(header_name(SECT_TYPE, GELF_ST_TYPE(shdr->sh_type)), "PROGBITS") == 0) {
if(strcmp(flag_name(SECT_FLAGS, shdr->sh_flags), "ALLOC & EXECUTE") == 0 || \
strcmp(flag_name(SECT_FLAGS, shdr->sh_flags), "EXECUTE") == 0) {
exe_sect = get_exe_sections(exe_sect, elf, ehdr, shdr, data);
struct _section *nxt_sect = (struct _section *)realloc(exe_sect, 2*sizeof(*exe_sect));
if(nxt_sect != NULL)
exe_sect = nxt_sect;
}
}
}
return 0;
}
What I am having trouble with is creating an array of structures dynamically and using malloc and realloc to resize the structure to fit more data into it. If I were to place a handful of print statements are the bottom of main the output will give me the last data that was input to the structure. How would I go about accessing individual entries that were made during each call to get_exe_section? From prior posts and other resources I thought this would work, but I cannot create an array in this manner. Any form of help would be great. Thanks.
You could add another element in your struct that points to the next section. This way you could create a linked list
struct _section {
char *sectName;
int start_addr;
int end_addr;
char *bytes;
struct _section *next; // pointer to next section
};
You could use another Struct to point to the head of your list.
and then instead of using realloc. you could just do
exe_sect->next = (struct _section *)malloc(sizeof(struct _section));
Here is how I would change the main function :
int main(int argc, char *argv[]) {
Elf *elf;
int fd;
//process input file
int sections_count = count_sections(elf);
GElf_Ehdr ehdr_mem;
GElf_Ehdr *ehdr = gelf_getehdr(elf, &ehdr_mem);
struct _section *exe_sect = (struct _section *)malloc(sizeof(struct _section));
for(int cnt = 0; cnt < sections_count; cnt++) {
Elf_Scn *scn = elf_getscn(elf, (size_t)cnt);
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr(scn, &shdr_mem);
Elf_Data *data = elf_getdata(scn, NULL);
if(ehdr == NULL || shdr == NULL)
exit(1);
if(strcmp(header_name(SECT_TYPE, GELF_ST_TYPE(shdr->sh_type)), "PROGBITS") == 0) {
if(strcmp(flag_name(SECT_FLAGS, shdr->sh_flags), "ALLOC & EXECUTE") == 0 || \
strcmp(flag_name(SECT_FLAGS, shdr->sh_flags), "EXECUTE") == 0) {
exe_sect = get_exe_sections(exe_sect, elf, ehdr, shdr, data);
exe_sect->next = (struct _section *)malloc(sizeof(struct _section));
if(exe_sect->next != NULL)
exe_sect = exe_sect->next;
}
}
}
return 0;
PS : To access all the individual entries, add another struct that consists of a pointer to the head of the list, and a variable that keeps count.

How to insert element into this struct

I am newer to C and do some practice,in this example,i want construct a table which can contains alot of element which is Symbol type,but i don't konw how to write that part.I want to use malloc to allocate heap memory to Symbol and insert into the table(SymbolTable).
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<string.h>
typedef struct {
char *name;
uint32_t addr;
}Symbol;
typedef struct {
Symbol* tbl;
uint32_t len;
uint32_t cap;
int mode;
} SymbolTable; /*this is the table i want to mantiply*/
SymbolTable* create_table(int mode) {
SymbolTable* st = (SymbolTable*)malloc(sizeof(SymbolTable));
if (st != NULL)
{
st->mode = mode;
st->len = 0;
return st;
}
printf("Memory allocation failed!\n");
return NULL;
}
void free_table(SymbolTable* table) {
int i;
for (i = 0; i < table->len; ++i)
{
free(table->tbl[i].name);
free(&(table->tbl[i]));
}
free(table);
}
int add_to_table(SymbolTable* table, const char* name, uint32_t addr) {
if (addr % 4 != 0)
{
printf("Address alignment erron!\n");
return -1;
}
int table_len = table->len;
if (table->mode == 1)
{
int i;
for (i = 0; i < table_len; ++i)
{
if (*((table->tbl[i]).name) == *name)
{
printf("Name existed!\n");
return -1;
}
`I don't know how to inset element here`
}
}
return 0;
}
int main()
{
SymbolTable * st = create_table(0);
add_to_table(st, "aaa", 4);
add_to_table(st, "bb", 8);
write_table(st, stdout);
free_table(st);
}
There are few problems with your code as it is; also, I had to make a few assumptions since you didn't specify those details in your question:
cap is the capacity of table->tbl, i.e. how much memory we have allocated
When adding a new symbol, we should copy the string containing its name, rather than just assigning that pointer to our new Symbol entry.
You should also pick one coding style and stick to it (braces on same vs new line, T* ptr vs T *ptr etc). Finally, I've removed the cast in create_table; see Do I cast the result of malloc?
Here is a fixed version of your code; in add_to_table, if we don't have enough memory to add a new one, we double the capacity of our Symbol array (calling realloc every single time to add space for one more element would be wasteful). When we extend the capacity of our array, we must take care to set each name pointer to NULL, because if we don't and free_table is called when cap > len, we'd be trying to free an uninitialized pointer (whereas calling free on NULL is perfectly fine and does nothing).
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef struct
{
char* name;
uint32_t addr;
} Symbol;
typedef struct
{
Symbol* tbl;
uint32_t len;
uint32_t cap;
int mode;
} SymbolTable; /*this is the table i want to mantiply*/
SymbolTable* create_table(int mode)
{
SymbolTable* st = malloc(sizeof(SymbolTable));
if (st != NULL)
{
st->tbl = NULL;
st->mode = mode;
st->len = 0;
st->cap = 0;
return st;
}
printf("Memory allocation failed!\n");
return NULL;
}
void free_table(SymbolTable* table)
{
int i;
for (i = 0; i < table->cap; ++i)
{
free(table->tbl[i].name);
}
free(table->tbl);
free(table);
}
int add_to_table(SymbolTable* table, const char* name, uint32_t addr)
{
if (addr % 4 != 0)
{
printf("Address alignment erron!\n");
return -1;
}
int table_len = table->len;
if (table->mode == 1)
{
int i;
for (i = 0; i < table_len; ++i)
{
if (!strcmp(table->tbl[i].name, name))
{
printf("Name existed!\n");
return -1;
}
}
if (table_len + 1 > table->cap)
{
// allocate more memory
uint32_t new_cap = table->cap ? table->cap * 2 : 2;
table->tbl = realloc(table->tbl, new_cap * sizeof(*table->tbl));
if (table->tbl == NULL)
{
// handle the error
}
table->cap = new_cap;
int i;
for (i = table_len; i < new_cap; ++i)
{
table->tbl[i].name = NULL;
}
}
uint32_t name_len = strlen(name);
table->tbl[table_len].name = malloc(name_len + 1);
strncpy(table->tbl[table_len].name, name, name_len);
table->tbl[table_len].name[name_len] = '\0';
table->tbl[table_len].addr = addr;
table->len++;
}
return 0;
}
int main(void)
{
SymbolTable* st = create_table(1);
add_to_table(st, "aaa", 4);
add_to_table(st, "bb", 8);
write_table(st, stdout);
free_table(st);
}
Firstly, I think you need to allocate *tbl and set cap (if he contain the max nb of cell in your table) in create_table().
Next, in add_to_table(), try to malloc(sizeof(struct symbol)) if (len < cap) and allocate memory for *name, and set up to your value (don't forget the \0 at the end of *name). Assign this to tbl[len] and do not forget to increment len.
Try to separate in little function, like int is_in_table(const char *name) who return the index or -1, or symbol new_symbol(const char *name, Uint32 addr) who create and set new symbol.
I hope that I have been useful for you :).
Use the concept of implementing Self-Referential structure.
Giving hints:
typedef struct S{
char *name;
uint32_t addr;
S* next;
}Symbol;
typedef struct {
Symbol* tbl;
uint32_t len;
int mode;
} SymbolTable;
http://www.how2lab.com/programming/c/link-list1.php
self referential struct definition?
Possible Implementation
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<string.h>
#include <stdio.h>
typedef struct S{
char *name;
uint32_t addr;
S* next;
}Symbol;
typedef struct {
Symbol* tbl;
uint32_t len;
int mode;
} SymbolTable; /*this is the table I want to maltiply*/
SymbolTable* create_table(int mode) {
SymbolTable* st = (SymbolTable*)malloc(sizeof(SymbolTable));
if (st != NULL)
{
st->tbl = NULL;
st->mode = mode;
st->len = 0;
return st;
}
printf("Memory allocation failed!\n");
return NULL;
}
void free_table(SymbolTable* table) {
free(table);
}
int add_to_table(SymbolTable* table, char* name, uint32_t addr) {
if (addr % 4 != 0)
{
printf("Address alignment erron!\n");
return -1;
}
int table_len = table->len;
if (table->mode == 1)
{
if (table_len == 0)
{
Symbol *t = (Symbol*)malloc(sizeof(Symbol));
t->name = name;
t->next = NULL;
table->len++;
table->tbl = t;
}
else
{
Symbol *t = table->tbl;
while (t->next != NULL)
{
if (t->name == name)
{
printf("Name existed!\n");
return -1;
}
t = t->next;
}
if (t->name == name)
{
printf("Name existed!\n");
return -1;
}
t->next = (Symbol*)malloc(sizeof(Symbol));
table->len++;
t->next->name = name;
t->next->next = NULL;
}
}
return 0;
}
void write_table(SymbolTable *st)
{
Symbol *t = st->tbl;
while (t != NULL)
{
printf("%s\n",t->name);
t = t->next;
}
printf("\n");
}
int main()
{
SymbolTable *st = create_table(0);
st->mode = 1;// Table mode setting to 1 for importing next value to table.
// You may implement it in your own way.
add_to_table(st, "cc", 8);
st->mode = 1;
add_to_table(st, "bb", 8);
st->mode = 1;
write_table(st);
free_table(st);
}

Segmentation fault while allocating memory for front element of a queue in C

I have Node and Queue structs in the file queue.h
#ifndef QUEUE_H
#define QUEUE_H
#include<stdio.h>
#include<stdbool.h>
typedef struct rcb
{
int seq_no;
int file_desc;
FILE *fp;
long sent;
long sizeOfFile;
char *request_http_method;
char *request_file;
char *request_http_version;
int level;
bool is_new_created;
int remaining;
}* RCB;
/*
* Node of the queue.
*/
typedef struct node {
RCB info; //Data of each node.
struct node *ptr;//pointer to the next node.
} * Node;
/*
* Queue for the requests.
*/
typedef struct req_queue {
Node front; //front node.
Node rear; //rear node.
int size; //size of the queue.
} * Queue;
/**
* Create the queue.
*/
void create(Queue queue);
/**
* For inserting an item to the queue in sorted order of file size.
* #param data
*/
void enque_SJF(Queue queue, RCB data);
#endif
queue.c
#include "queue.h"
Node temp, front1;
int count = 0;
/**
* For creating the queue.
*/
void create(Queue queue) {
queue->front = queue->rear = NULL;
queue->size=0;
}
/**
* Enqueing in the order of increasing file size.
* #param data
*/
void enque_SJF(Queue que, RCB data) {
bool found = false;
Node temp = que->front;
while (!found) {
if (que->front == NULL) { //if the queue is empty.
que->front = malloc(sizeof (struct node));
que->front->ptr = NULL;
que->front->info = data;
que->rear = que->front;
break;
} else {
if (temp->ptr == NULL) {
Node newnode = (struct node *) malloc(1 * sizeof (struct node));
newnode->info = data;
if (temp->info->sizeOfFile >= data->sizeOfFile) {
newnode->ptr = temp;
que->front = newnode;
break;
} else { //else enqueue at the rear.
temp->ptr = newnode;
}
} else {
if (temp == que->front && temp->info->sizeOfFile >= data->sizeOfFile) {
Node newnode = (struct node *) malloc(1 * sizeof (struct node));
newnode->info = data;
newnode->ptr = temp;
que->front = newnode;
break;
}
if (temp->ptr->info->sizeOfFile >= data->sizeOfFile) {
Node newnode = (struct node *) malloc(1 * sizeof (struct node));
newnode->info = data;
newnode->ptr = temp->ptr;
temp->ptr = newnode;
break;
} else
temp = temp->ptr;
}
}
}
que->size++;
}
I am trying to enqueue a new node to a queue in the function enque_SJF in queue.c file. The enqueue function is called in sws.c by the function serve_client function. Here is the sws.c There are some more functions in those files but they are not related with my problem so i didnt wrote all functions to be more simple;
#include "Queue.h"
#include "network.h"
#include "schedulers.h"
#include "shared.h"
char scheduler[4];
pthread_t tid[2];
int port;
Queue req_queue;
bool flag[2];
int turn;
int sequence_number;
void *serve_client()
{
static char *buffer; /* request buffer */
int fd;
req_queue = (struct req_queue *) malloc( sizeof (struct req_queue));
create(req_queue);
if (port != 0)
{
network_init( port ); /* init network module */
fprintf(stderr, "Connection port %d\n", port);
for( ;; )
/* main loop */
{
network_wait();
if( !buffer ) /* 1st time, alloc buffer */
{
buffer = malloc( MAX_HTTP_SIZE );
if( !buffer ) /* error check */
{
perror( "Error while allocating memory" );
abort();
}
}
for( fd = network_open(); fd >= 0; fd = network_open() ) /* get clients */
{
memset( buffer, 0, MAX_HTTP_SIZE );
if( read( fd, buffer, MAX_HTTP_SIZE ) <= 0 ) /* read req from client */
{
perror( "Error while reading request" );
abort();
}
printf("file path %s\n",buffer);
//Initializing memory for the job.
RCB request = (RCB) malloc(1 * sizeof (struct rcb));
//breaking the request in appropriate format.
request-> request_http_method = strtok(buffer, " "); //request method.
request->request_file = strtok(NULL, " /"); //request file
request->request_http_version = strtok(NULL, "\n"); //HTTP version
request->file_desc = fd;
request->level = 1; // for multilevel scheduler.
request->seq_no = sequence_number;
sequence_number++; //increment global counter.
enque_SJF(req_queue, request); //Enqueue for Shortest Job First.
}
}
}
return 0;
}
bool isValidRequest(RCB request)
{
// the request is parsed and checked the validity
}
void *SJF( )
{
// function implemented
}
int main(int argc, char **argv )
{
//default port, if no port is supplied.
/* check for and process parameters
*/
if( ( argc < 3 ) || ( sscanf( argv[1], "%d", &port ) < 1 ) || ( sscanf( argv[2], "%s", scheduler ) < 1 ) )
{
printf("port %d\n",port);
printf("port %s\n",scheduler);
printf( "usage: sms <port> <scheduler>\n" );
return 0;
}
sequence_number = 1; //counter for number of requests.
if (argc == 3)
{
port = atoi(argv[1]);
}
printf("port %d\n",port);
pthread_create(&(tid[0]), NULL, serve_client, NULL);
if(strcmp(scheduler,"SJF") ==0)
{
pthread_create(&(tid[1]), NULL, SJF, NULL);
}
else if(strcmp(scheduler,"RR")==0)
{
pthread_create(&(tid[1]), NULL, Round_Robin, NULL);
}
else if(strcmp(scheduler,"MLFB")==0)
{
pthread_create(&(tid[1]), NULL, MultilevelQueueWithFeedback, NULL);
}
else
{
printf("Scheduler Algorithm is not defined. Please enter one of them; SJF, RR, MLFB");
return 0;
}
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
return 0;
}
While adding a new node to the queueu i am getting a segmentation fault error at the following line;
que->front->ptr = NULL;
While debugging, i see that after memory allocation the address for que->front is still 0x0. Is there any suggestion why it does not allocate memory?
That is why you should always perform success check for the called function(s).
In case, if malloc() is failure, it will return a NULL pointer which gets stored in que->front. After that, without a NULL check, if you try to access
que->front->ptr
you'll be de-referencing a NULL pointer (i.e, accessing invalid memory) which invokes undefined behavior.
Always do a NULL check on the return value of malloc().

Returning structures from functions. C

I am new to C and programming as a whole. I am trying to create a simple file validation program that reads in records from a file and sorts valid from invalid records. I have managed to achieve this but have run into problems when trying to return the structs for use in the main program.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define MAX 20
typedef struct data{
int ref;
int serial;
char string[MAX+1];
}vaild,invalid;
int g = 1;
int e = 1;
void read(FILE *file);
void val(struct data* t);
void create_record(struct data* temp);
void create_error(struct data* temp);
void export_data(struct data* record, struct data* error);
int main(){
FILE *file = fopen("file.txt", "r");
if (file != NULL){
read (file);
I want to be able to call the structures 'valid and 'invalid' from here inside the main function. Like the commented out printf function below.
//printf("%i", valid[1].ref); <<<<<<<<<< I need to be able to play around with the structures from inside the main function!
}
return 0;
}
void read(FILE *file){
struct data* t = malloc(sizeof(struct data));
char buf[1000];
while(!feof(file)){
fgets(buf, sizeof buf, file);
sscanf(buf, "%d.%d.%s", &t->ref, &t->serial, t->string);
val(t);
}
}
void val (struct data* t){
if((t->ref < 30)){
struct data* valid = (struct data*) malloc(sizeof(struct data));
valid = (struct data*)realloc(valid, g * sizeof(struct data));
valid[g-1] = *t;
if (valid == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nGOOD:%i.%i.%s\n", valid[g-1].ref, valid[g-1].serial, valid[g-1].string);
g++;
}
else{
struct data* invalid = (struct data*) malloc(sizeof(struct data));
invalid = (struct data*)realloc(invalid, e * sizeof(struct data));
invalid[e-1] = *t;
if ( invalid == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nBAD:%i.%i.%s\n", invalid[e-1].ref, invalid[e-1].serial, invalid[e-1].string);
e++;
}
}
I cant seem to be able to call the structures from within main by using the return functions, I feel I must be doing something really simple wrong. Getting pretty frustrated.
The input file is like so:
04.06.hello
09.65.test
88.55.string
27.12.qwerty
11.53.ytrewq
92.02.ecco
Everything else is working fine and there are no compiler errors. I have changed all the return types to void to make it less messy, I think I must be using them wrong.
Found your problem
void val (struct data* t){
if((t->ref < 30)){
struct data* valid = (struct data*) malloc(sizeof(struct data));
valid = (struct data*)realloc(valid, g * sizeof(struct data));
valid[g-1] = *t;
if (valid == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nGOOD:%i.%i.%s\n", valid[g-1].ref, valid[g-1].serial, valid[g-1].string);
g++;
}
else{
struct data* invalid = (struct data*) malloc(sizeof(struct data));
invalid = (struct data*)realloc(invalid, e * sizeof(struct data));
invalid[e-1] = *t;
if ( invalid == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nBAD:%i.%i.%s\n", invalid[e-1].ref, invalid[e-1].serial, invalid[e-1].string);
e++;
}
}
In above code when you define valid and invalid inside If and else if , scope of these variables are inside those if conditions. So you will get "valid not defined" error.
Try this
struct data* val(struct data* t){
if((t->ref < 30)){
struct data* valid_file = (struct data*) malloc(sizeof(struct data));
valid_file = (struct data*)realloc(valid_file, g * sizeof(struct data));
valid_file[g-1] = *t;
if (valid_file == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nGOOD:%i.%i.%s\n", valid_file[g-1].ref, valid_file[g-1].serial, valid_file[g-1].string);
g++;
return valid_file;
}
// Will come when result is invalid
struct data* invalid_file = (struct data*) malloc(sizeof(struct data));
invalid_file = (struct data*)realloc(invalid_file, e * sizeof(struct data));
invalid_file[e-1] = *t;
if ( invalid_file == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nBAD:%i.%i.%s\n", invalid_file[e-1].ref, invalid_file[e-1].serial, invalid_file[e-1].string);
e++;
return invalid_file;
}
Note - Changed valid and invalid to different variable names to separate struct name definitions.
Complete working example :)
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define MAX 20
typedef struct data{
int ref;
int serial;
char string[MAX+1];
}vaild,invalid;
int g = 1;
int e = 1;
struct data* read(FILE *file);
struct data* val(struct data* t);
void create_record(struct data* temp);
void create_error(struct data* temp);
void export_data(struct data* record, struct data* error);
int main(){
FILE *file = fopen("file.txt", "r");
if (file != NULL){
struct data* answ=read (file);
printf("%i \n", answ->ref);
}
return 0;
}
struct data* read(FILE *file){
struct data* t = malloc(sizeof(struct data));
char buf[1000];
while(!feof(file)){
fgets(buf, sizeof buf, file);
sscanf(buf, "%d.%d.%s", &t->ref, &t->serial, t->string);
val(t);
}
return t;
}
struct data* val(struct data* t){
if((t->ref < 30)){
struct data* valid_file = (struct data*) malloc(sizeof(struct data));
valid_file = (struct data*)realloc(valid_file, g * sizeof(struct data));
valid_file[g-1] = *t;
if (valid_file == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nGOOD:%i.%i.%s\n", valid_file[g-1].ref, valid_file[g-1].serial, valid_file[g-1].string);
g++;
return valid_file;
}
// Will come when result is invalid
struct data* invalid_file = (struct data*) malloc(sizeof(struct data));
invalid_file = (struct data*)realloc(invalid_file, e * sizeof(struct data));
invalid_file[e-1] = *t;
if ( invalid_file == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nBAD:%i.%i.%s\n", invalid_file[e-1].ref, invalid_file[e-1].serial, invalid_file[e-1].string);
e++;
return invalid_file;
}
Returning a struct in C is acceptable when the struct is small. Otherwise you'd be better off using pointers.
The snippet below is a simple example that shows you how to return a struct.
Same rules apply as returning any other data type (e.g., int, double, ...), return types need to match and the function needs to have a return statement.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} Point;
Point init_point(Point p, int x, int y) {
p.x = x;
p.y = y;
return p;
}
void main() {
Point p1, p2;
printf("%d, %d\n", p1.x, p1.y);
printf("%d, %d\n", p2.x, p2.y);
p1 = init_point(p1, 55, 10);
printf("%d, %d\n", p1.x, p1.y);
printf("%d, %d\n", p2.x, p2.y);
p2 = init_point(p2, 10000, 190);
printf("%d, %d\n", p1.x, p1.y);
printf("%d, %d\n", p2.x, p2.y);
}
The result is :
-1080464084, -1080464264
1, -1080464092
55, 10
1, -1080464092
55, 10
10000, 190

"Paranormal" activity in queue structure

#include <stdio.h>
#include <stdlib.h>
/* Report an error and abort */
#define FATAL_ERROR(message) \
{ \
fprintf(stderr,"In %s(%d) [function %s]: %s\n", \
__FILE__, __LINE__, __FUNCTION__ , (message) ); \
abort(); \
} \
/* Report a posix error (similar to perror) and abort */
#define FATAL_PERROR(errcode) FATAL_ERROR(strerror(errcode))
void* Malloc(size_t n)
{
void* new = malloc(n);
if(new==NULL) FATAL_ERROR("Out of memory.");
return new;
}
typedef struct twit{
char data[141]; //contains the actual data
//struct twit *prev; //pointer to previous node (Closer to front)
struct twit *next; //pointer to next node (Closer to back)
}twit;
typedef struct twitbuffer{
twit *first;
twit *last;
int size;
}twit_buffer;
/*
function for create a new buffer
*/
void new_twitbuffer(twit_buffer *a)
{
a=Malloc(sizeof(twit)*12000);
a->first = a->last = NULL;
a->size = 0;
return;
}
int twitbuffer_empty(twit_buffer *a) {
if(a->first == NULL)
return 1;
else
return 0;
}
/*
function to insert a new twit in the buffer
*/
void insertTwit(twit_buffer *a, char *data)
{
twit new;
if (strlen(&data)<=140){
strcpy(&new.data,data);
}
else{
printf("Twit > 140 characters...");
}
if (new.data == NULL) {
//errno = ENOMEM;
printf("error!");
return;
}
if(a->first==NULL){
a->first = a->last = &new;
}else{
a->last->next=&new;
a->last=&new;
}
new.next= NULL;
a->size++;
return;
}
char* popTwit(twit_buffer *a) {
if (twitbuffer_empty(a)) {
return NULL;
}
char *data;
//strcpy(&data,a->first->data);
data=a->first->data;
if (a->first == a->last)
a->first = a->last = NULL;
else
a->first = a->first->next;
a->size--;
return data;
}
twit_buffer mytwitbuffer;
int main()
{
new_twitbuffer(&mytwitbuffer);
//printf("a=%d",mytwitbuffer);
char *a = "first twit\n";
char *b = "second twit\n";
char *c = "third twit\n";
insertTwit(&mytwitbuffer, a);
insertTwit(&mytwitbuffer, b);
insertTwit(&mytwitbuffer, c);
char *poppp;
poppp = popTwit(&mytwitbuffer);
printf("%s", poppp);
poppp = popTwit(&mytwitbuffer);
printf("%s", poppp);
poppp = popTwit(&mytwitbuffer);
printf("%s", poppp);
}
This is my code for an implementation of a queue. When i execute this i take this result:
thir�it
(null)(null)
This means that the two first insertions are not being done correctly and the third goes in stdout in a "paranormal" way! Do you have any ideas?
You are storing a reference to the local variable 'new' in your twit buffer. You should Malloc it, instead Of declaring It local

Resources