Loading binary file - realloc(): invalid next size - c

I am trying to load a binary file but I am getting:
realloc(): invalid next size
This is the struct im using in the following code:
typedef struct {
int from;
int to;
int cost;
} edge_t;
typedef struct {
int size;
int capacity;
edge_t *edges;
} graph_t;
Code:
#include <stdlib.h>
#include <stdio.h>
#include "graph.h" //this is the struct above
void load_bin(const char *fname, graph_t *graph) {
graph->capacity = 1;
graph->size = 0;
graph->edges = malloc(graph->capacity*sizeof(edge_t));
FILE *myFile;
myFile = fopen(fname, "r");
if (myFile == NULL) {
fprintf(stderr, "Error: file not found!\n");
exit(100);
}
while(fread(&(graph->edges[graph->size].from), sizeof(edge_t), 3, myFile) == 3){
graph->size++;
if(graph->capacity == graph->size){
graph->capacity *=2;
graph->edges=realloc(graph->edges, sizeof(edge_t)*graph->capacity);
}
}
}
EDIT: Tried to make a verifiable example, as requested.
int main(int argc, char *argv[])
{
int ret = 0;
if (argc > 2) {
graph_t *graph = allocate_graph();
fprintf(stderr, "Load bin file '%s'\n", argv[1]);
load_bin(argv[1], graph);
fprintf(stderr, "Save txt file '%s'\n", argv[2]);
save_txt(graph, argv[2]);
free_graph(&graph);
} else {
fprintf(stderr, "Usage %s input_bin_file output_txt_file\n", argv[0]);
ret = -1;
}
return ret;
}
This function and load are located in the same file and are called from main
graph_t *allocate_graph(){
return calloc(1, sizeof(graph_t));
}
From what I checked, it means I do not change the size properly on realloc, but I thought i was?
Thanks.

the while is invalid, must be
while(fread(&(graph->edges[graph->size].from), sizeof(edge_t), 1, myFile) == 1)
because currently you read 3 elements and go out of the allocated memory
P.S. out of that, are you sure you read correctly the file ? you suppose the content is consecutive 3 values on sizeof(int) bytes, without separator etc

Related

how to read value in structure

I'm reading file using fread().[read file only]
On compilation, the compiler throws a "Segmentation fault (core dumped)" error.
I'm using structure.
I wrote this code.
type #include <string.h>
#include <stdio.h>
#include <stdlib.h>
int twilio_send_functionapi(char *channel, char *status); // function declartion
struct credentials
{
char *account_sid;
char *auth_token;
char *from_number;
char *to_number;
} c1;
int main(int argc, char *argv[])
{
FILE *fp;
struct credentials input;
fp = fopen("data.config", "r");
if (fp == NULL)
{
printf("Error\n");
return -1;
}
dentials.to_number = (char*)malloc(sizeof(char)*100);
while(fread(&c1,sizeof(struct credentials),1 ,fp))
fscanf(fp,"%s %s %s %s", c1.account_sid, c1.auth_token,c1.from_number, c1.to_number);
char *channel,*status;
channel = argv[1];
status = argv[2];
twilio_send_functionapi(channel,status); //function call
}
Don't know where I'm mistaken.
here is .conf file which needs to be read
account_sid : AC40cfb4f3e98b55b13a9b93527683171e
auth_token : 5f6906d7847ad1fc1fc1170ab60e40fd
from_number : 15867854760
to_number : 1212321123
Instead of fread(), fscanf(), use fgets() to read a line of the file into a string.
// 123456789 123456789 123456789 123456789
//account_sid : AC40cfb4f3e98b55b13a9b93527683171e
#define SID_LEN 34
struct credentials {
char account_sid[SID_LEN + 1]; // Use array here, not pointer.
// ... omitted for brevity
} c1;
#define LINE_SIZE 100
char line[LINE_SIZE];
if (fgets(line, sizeof line, fp)) {
if (sscanf(line, "account_sid : %34s", c1.account_sid) == 1) {
; // Success
} else {
; // Failed
}
Continue likewise for the other c1 members`.
Thank you everyone.
I resolve my problem.
char credential[4][100] ;
int main()
{
FILE *fp;
fp = fopen("data.config", "r");
if (fp == NULL)
{
printf("Error\n");
return -1;
}
printf("File is opened\n");
if ((fscanf(fp,"account_sid-%s\n",credential[0])!= 1))
{
printf("error reading account_sid value\n");
return -1;
}
fclose(fp);
}

Why is fscanf() seg faulting while trying to read from a file?

I am using C in Visual Studio via a remote Linux server. I want to read a file and store the contents in a array of structs. Every time I try to read a line using fscanf() it seg faults. Thanks in advance.
Format of the file I'm trying to read:
F150 5.4 28000 white
RAM1500 5.7 32000 orange
car 4.5 12000 green
truck 6.1 55000 black
Here's a simplified version my program as the other parts function fine:
#include <stdlib.h>
#include <stdio.h>
struct data {
char name[20];
float floatNum;
int intNum;
char color[20];
} temp;
int scan(void) {
int size = 0;
FILE *data;
data = fopen("./hw3.data", "r");
while (1) {
fscanf(data, "%s %f %d %s", temp.name, &temp.floatNum,
&temp.intNum, temp.color);
if (feof(data))
break;
size++;
}
return size;
}
void load(int size, struct data autos[]) {
int i;
FILE *data;
data = fopen("./hw3.data", "r");
for (i = 0; i < size; i++) {
fscanf(data, "%s %f %d %s", autos[i].name, &autos[i].floatNum,
&autos[i].intNum, autos[i].color);
}
}
int main() {
int size;
struct data *autos;
size = scan();
autos = malloc(size * sizeof(struct data));
load(size, autos);
return 0;
}
There are multiple possible causes for problems:
you do not test if fopen() succeeds: if the file cannot be opened, the FILE pointer data will be null, causing undefined behavior in fscanf(), possibly a seg fault.
you do not test if malloc succeeds... again causing a seg fault if memory cannot be allocated.
you should close the FILE after reading
your test for feof() is incorrect: it might be true after successfully reading the last item, causing it to be ignored and you might never reach the end of file if one of the items cannot be read. You should just test the return value of fscanf(): it returns the number of successful conversions, so 4 in your case.
you should use %19s to avoid writing beyond the end of the targets arrays, another potential source of undefined behavior.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct data {
char name[20];
float floatNum;
int intNum;
char color[20];
};
int scan(const char *filename) {
struct data temp;
int size = 0;
FILE *data = fopen(filename, "r");
if (data == NULL) {
fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
return -1;
}
while (fscanf(data, "%19s %f %d %19s",
temp.name, &temp.floatNum,
&temp.intNum, temp.color) == 4) {
size++;
}
fclose(data);
return size;
}
int load(const char *filename, int size, struct data autos[]) {
int i;
FILE *data = fopen(filename, "r");
if (data == NULL) {
fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
return -1;
}
for (i = 0; i < size; i++) {
if (fscanf(data, "%19s %f %d %19s",
autos[i].name, &autos[i].floatNum,
&autos[i].intNum, autos[i].color) != 4)
break;
}
fclose(data);
return i;
}
int main() {
char filename[] = "./hw3.data";
int size = scan(filename);
if (size < 0)
return 1;
if (size > 0) {
struct data *autos = malloc(size * sizeof(struct data));
if (autos == NULL) {
fprintf(stderr, "cannot allocate %zu bytes\n", size * sizeof(struct data));
return 1;
}
int n = load(filename, size, autos);
for (int i = 0; i < n; i++) {
printf("%s %g %d %s\n", autos[i].name, autos[i].floatNum,
autos[i].intNum, autos[i].color);
}
free(autos);
}
return 0;
}

Is there any encoding problems?

I am trying to write these parameters in a file .txt, but when I open the file (even before that it shows me a warining about the encoding) it appers like a bug, full of ????, like this:
$�U�z�G��?xpto%�U\���(\�?xpto&�Uףp=
��?xpto'�UR���Q�?xpto(�U�������?xpto)�UH�z�G�?xpto*�U��(\���?xpto+�U>
ףp=�?xpto,�U���Q��?xpto-�U433333�?xpto
I've searched a lot about but as it is a specifically error, i cannot find nothing about it.
What is happening?
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
typedef struct
{
int age;
double height;
char name[64];
} Person;
void printPersonInfo(Person *p)
{
printf("Person: %s, %d, %f\n", p->name, p->age, p->height);
}
int main (int argc, char *argv[])
{
FILE *fp = NULL;
int i;
Person p = {35, 1.65, "xpto"};
/* Validate number of arguments */
if(argc != 2)
{
printf("USAGE: %s fileName\n", argv[0]);
return EXIT_FAILURE;
}
/* Open the file provided as argument */
errno = 0;
fp = fopen(argv[1], "w");
if(fp == NULL)
{
perror ("Error opening file!");
return EXIT_FAILURE;
}
/* Write 10 itens on a file */
for(i = 0 ; i < 10 ; i++)
{
p.age = p.age+1;
p.height = p.height+0.03;
fwrite(&p, sizeof(Person), 1, fp);
}
fclose(fp);
return EXIT_SUCCESS;
}
The fwrite function is writing the binary representation of the struct p to the file. If you want to write text, use fprintf:
fprintf(fp, "%d %f %s\n", p.age, p.height, p.name);

INI file reader function is addressing wrong values to my structure, How do I solve this?

This is for a project for university (small replica of a Catan game) and I'm struggling a bit with this part, we have the read an INI file with fairly simple formatting, it only has some comments starting with ';' and then it's just tags with a value in front:
xdim=4
ydim=5
N=D
S=L2
E=S10
W=D
etc...
I have this function to read from an INI file and address the read values to the correct struct element. But it seems like it doesn't even read the file, the struct is a simple struct with xdim and ydim, after I call the func xdim is '&d&d&d&d etc...' and ydim is 0
I've tried placing in some printf's just to see if the values from the INI file itself where being read wrong, but nothing is printed.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 128
typedef struct UNIT { /**struct used in an array for the rest of the INI values*/
char N[4];
char S[4];
char W[4];
char E[4];
char Building;
}UNIT;
typedef struct{ /**This is declared in main and passed to the functions*/
UNIT *grid;
unsigned int xdim;
unsigned int ydim;
} MAP_CONFIG;
void set_config_val(MAP_CONFIG *config, const char *key, int val) {
if (config == NULL)
return;
if (strcmp(key, "xdim") == 0){
printf("here");
config->xdim = val;
}
else if (strcmp(key, "ydim") == 0){
printf("here");
config->ydim = val;
}
else{
;
}
}
void read_config(MAP_CONFIG *config,FILE *f) {
char str[MAX];
char *token;
const char *delim = "=\n";
while (1) {
fgets(str, MAX, f);
if(feof(f)!= 0) break;
puts(str);
if (strchr(str, '=')!=NULL) {
char varname[MAX];
int value;
token = strtok(str, delim);
strcpy(varname, token);
token = strtok(NULL, delim);
value = atoi(token);
printf("&d", token);
set_config_val(config, varname, value);
}
}
config = malloc(sizeof(MAP_CONFIG));
config->grid = calloc(config->xdim * config->ydim, sizeof(UNIT));
close(f);
return;
}
open file function:
FILE *openFile(char *nome, char *mode) {
FILE *f;
printf("Opening file %s\n", nome);
f = fopen(nome, mode);
if (f == NULL) {
fprintf(stderr, "*** It was not possible to open the file %s.", nome);
exit(1);
}
return f;
}
test main im using:
int main(int argc, char **argv) {
MAP_CONFIG map;
MAP_CONFIG *mapa = &map;
FILE *f;
char *filename;
for (int i = 0; i < argc; i++)
printf("Parametro %d: %s\n", i, argv[i]);
if (argc >= 2) {
filename = argv[1];
}
else {
printf("Opening base map file..\n");
filename = "mapa.ini";
}
f = openFile(filename, "r");
read_config(mapa, f);
printf("%d %d", map.xdim, map.ydim);
return 0;
}
I just want it to read the xdim and ydim, and then repeat the process to an array of structs for each struct to get the correct value of the N,S,E,W present in the INI file... Help!

C dynamic array of structures, no errors, program terminates when ran

When ran, the program immediately terminates from an issue I believe to be associated with memory allocation. The main function only calls this function and another to delete the memory allocated
DrinkMachine *create(void){
FILE *inFile;
//Pointer to data structure
DrinkMachine *drinkMachine;
// Memory allocation
drinkMachine = calloc(1, sizeof(DrinkMachine));
if(drinkMachine == NULL) // Check success
return NULL;
// Open the input file for reading
inFile = fopen("drink_machine.txt" , "r");
if(!inFile){
puts("Error opening file");
return NULL;
}
// Read drink count from file
fscanf(inFile, "%d", &(drinkMachine->numItems));
printf("DEBUG read file arrayLen: %d\n", drinkMachine->numItems);
// Dynamically create array of drink item structures
drinkMachine->drinkItem = malloc(drinkMachine->numItems*sizeof(DrinkItem));
if(drinkMachine->drinkItem == NULL){
puts("ERROR: Failed to allocate memory");
return NULL;
}
// Put information from file into drinkItem structs
for(int i=0; i < drinkMachine->numItems; ++i){
fscanf(inFile, "%s %lf %d", (drinkMachine->drinkItem[i].name), &(drinkMachine->drinkItem[i].price), &(drinkMachine->drinkItem[i].drinkLeft));
printf("DEBUG drink %d is: %s %lf %d\n", i, (drinkMachine->drinkItem[i].name), (drinkMachine->drinkItem[i].price), (drinkMachine->drinkItem[i].drinkLeft));
}
// Close inFile
fclose(inFile);
// Force output to screen
puts("DEBUG readFile Success!");
fflush(stdout);
return drinkMachine;
}
The program ran into errors or wouldn't properly allocate memory and would successfully output the error message when ran, until I put in the line:
drinkMachine->drinkItem = malloc(drinkMachine->numItems*sizeof(DrinkItem));
At this point the program compiles without warning or errors, but terminates immediately when ran without any output. In case it helps, here are the structures:
typedef struct _DrinkItem{
int id;
char *name;
double price;
int drinkLeft;
int drinkSold;
} DrinkItem;
typedef struct _DrinkMachine{
int version;
int numItems;
int drinkLocation;
DrinkItem *drinkItem;
} DrinkMachine;
You have to allocate storage for each name too. You are reading characters into an unallocated pointer on line 30. You should read the name into a temporary array, get the name’s length, allocate (length+1) bytes of storage to name, and strncpy the data over.
You didn't allocate name space, you didn't handle any input error, you use int without verify that it not negative for a size, you didn't use stderr for error, you used reserved identifier and more.
Here a proposition of code, that I think fix all your errors (didn't test it as you didn't give example of input and output):
#include <stdio.h>
#include <stdlib.h>
typedef struct DrinkItem {
int id;
char *name;
double price;
int drinkLeft;
int drinkSold;
} DrinkItem;
typedef struct DrinkItem {
int version;
size_t numItems;
int drinkLocation;
DrinkItem *drinkItems;
} DrinkMachine;
static void helper_free(DrinkItem *drinkItems, size_t n) {
for (size_t i = 0; i < n; i++) {
free(drinkItems[i].name);
}
free(drinkItems);
}
DrinkMachine *create(char const *path) {
FILE *inFile = fopen(path, "r");
if (!inFile) {
fprintf(stderr, "Error opening file");
return NULL;
}
size_t numItems;
if (fscanf(inFile, "%zu", &numItems) != 1) {
fprintf(stderr, "Error parsing\n");
return NULL;
}
#ifndef NDEBUG
printf("DEBUG read file arrayLen: %zu\n", numItems);
#endif
DrinkItem *drinkItems = malloc(numItems * sizeof *drinkItems);
if (!drinkItems) {
fprintf(stderr, "ERROR: Failed to allocate memory");
return NULL;
}
for (size_t i = 0; i < numItems; ++i) {
char *name = malloc(100);
if (!name) {
helper_free(drinkItems, i);
fprintf(stderr, "ERROR: Failed to allocate memory");
return NULL;
}
double price;
int drinkLeft;
if (fscanf(inFile, "%99s %lf %d", name, &price, &drinkLeft) != 3) {
free(name);
helper_free(drinkItems, i);
fprintf(stderr, "Error parsing\n");
return NULL;
}
drinkItems[i] =
(DrinkItem){.name = name, .price = price, .drinkLeft = drinkLeft};
#ifndef NDEBUG
printf("DEBUG drink %zu is: %s %lf %d\n", i, name, price, drinkLeft);
#endif
}
fclose(inFile);
DrinkMachine *drinkMachine = malloc(sizeof *drinkMachine);
if (!drinkMachine) {
helper_free(drinkItems, numItems);
fprintf(stderr, "ERROR: Failed to allocate memory");
return NULL;
}
*drinkMachine =
(DrinkMachine){.drinkItems = drinkItems, .numItems = numItems};
#ifndef NDEBUG
puts("DEBUG readFile Success!\n");
#endif
return drinkMachine;
}

Resources