I'm trying to write a program that manipulates ppm image files, works fine with relatively small files up to 622x1023 or so, but with a file any bigger the program throws a segfault error.
I have isolated the problem to this function:
void img2list(FILE *fp,int x,int y,int bd,int *resultado,long tamano){
int dimx=x,dimy=y;
int bitDepth=bd;
long numeroPixeles=(dimx*dimy*bitDepth);
int con=0;
int pixels[numeroPixeles];
while (!feof(fp)){
pixels[con]=fgetc(fp);
con++;
}
memcpy(resultado,pixels,tamano);
}
specifically to:
feof(fp)
and
fgetc(fp)
I'm compiling the code with this command:
gcc main.c -o pim
And I'm running Ubuntu 19.04 on a core i7 5820k with 16GB of RAM
Here's the entire code:
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int * getMeta(FILE *fp){
static int meta[3];
size_t len = 0;
char * line = NULL;
char delim[] = " ";
getline(&line,&len,fp);
getline(&line,&len,fp);
char *ptr1 = strtok(line, delim);
char *ptr2 = strtok(NULL, delim);
sscanf(ptr1, "%d", &meta[0]);
sscanf(ptr2, "%d", &meta[1]);
getline(&line,&len,fp);
char *ptr3 = strtok(line, delim);
sscanf(ptr3, "%d", &meta[2]);
return meta;
}
void img2list(FILE *fp,int x,int y,int bd,int *resultado,long tamano){
int dimx=x,dimy=y;
int bitDepth=bd;
long numeroPixeles=(dimx*dimy*bitDepth);
int con=0;
int pixels[numeroPixeles];
while (!feof(fp)){
pixels[con]=fgetc(fp);
con++;
}
memcpy(resultado,pixels,tamano);
}
void list2file(int *pixeles,int x,int y,int bitDepth, char nombre[]){
int dimx = x, dimy = y;
long numeroPixeles = dimx*dimy*bitDepth;
FILE *archivo = fopen(nombre, "wb"); /* b - binary mode */
(void) fprintf(archivo, "P6\n%d %d\n255\n", dimx, dimy);
for(long i=0;i<numeroPixeles;i++){
(void) fprintf(archivo,"%c",(char)pixeles[i]);
}
(void) fprintf(archivo,"\n");
(void) fclose(archivo);
}
int main(void){
int *meta;
int values,dimx,dimy;
int bitDepth=3;
FILE *fp = fopen("test.ppm","rb");
meta=getMeta(fp); // Dimenciones de la imagen
dimx = meta[0];
dimy = meta[1];
values = meta[2];
printf("dimencion en x: %d\n",dimx);
printf("dimencion en y: %d\n",dimy);
printf("cantidad de valores por pixel: %d\n",values);
long tamano=(dimx*dimy*bitDepth*sizeof(int));
int *pixeles=malloc(tamano);
img2list(fp,dimx,dimy,3,pixeles,tamano);
char nombre[]="pena.ppm";
list2file(pixeles,dimx,dimy,bitDepth,nombre);
(void) fclose(fp);
return EXIT_SUCCESS;
}
Thanks.
This:
int pixels[numeroPixeles];
is a stack overflow unless numeroPixeles is bounded by a small constant. Allocating large objects on the stack admits no way to distinguish success/failure; your program just blows up (and possibly yields code execution under the control of whoever authored the data you're processing). To work with arbitrary-size data like this you need malloc where you can check for success.
Related
I am fairly new to C and i have some questions. The task was to read the input.txt file and to first determine the number of lines (which i succesfully did). However the next task is to read the file line by line and to save each lines information into a struct. As you can see the task is also focused on creating as many functions as possible and that is where i am struggling right now. However i only want help with the "void readInputData" part. If someone could explain to me where my mistake is (why nothing is being printed) and maybe explain how to call the function properly in the main function that would be great. the output file wasnt part of the task i created it for myself to find some errors.
Input.txt :
1. M 17 160 13.24
2. M 18 177 13.22
3. M 15 162 14.78
4. F 16 169 15.55
5. F 16 161 14.73
6. F 16 160 10.80
7. M 14 192 15.65
8. F 18 197 12.41
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int iNumberOfLines = 1;
typedef struct {
char ignore[2];
char Gender;
int Age;
int Height;
float Time;
} Student_t;
Student_t *pStudents;
int determineNumberOfLines(FILE *pInputFile);
void readInputData(FILE *pInputFile, FILE *output, int iNumberOfLines, Student_t *pStudents);
// void calculateAverages(double *dAvHeight, double *dAvAge, double *dAvTime, Student_t *pStudents, int iNumberOfLines);
// Student_t* searchFastest(Student_t *pStudents, int iNumberOfLines);
// void printToConsole(Student_t *pFastestStudent, double dAvHeight, double dAvAge, double dAvTime);
int main(int argc, char *argv[]) {
FILE *pInputFile = fopen ("resources/Input.txt", "r");
if (pInputFile == NULL){
printf("Fehler beim Öffnen");
return -1;
}
FILE *output = fopen ("resources/Output.txt", "w");
if (output == NULL){
printf("Fehler beim Öffnen");
return -1;
}
printf("LINES: %d\n",determineNumberOfLines(pInputFile));
Student_t *pStudents;
readInputData(pInputFile, output, iNumberOfLines, pStudents);
return 0;
}
int determineNumberOfLines(FILE *pInputFile){
int ch;
while(!feof(pInputFile))
{
ch = fgetc(pInputFile);
if(ch == '\n')
{
iNumberOfLines++;
}
}
return iNumberOfLines;
fclose(pInputFile);
}
void readInputData(FILE *pInputFile, FILE *output, int iNumberOfLines, Student_t *pStudents){
int i = 0;
char buffer [120];
while (fgets(buffer, 120, pInputFile) != 0) //ließt zeile und speichert in "buffer" als string
{
if (sscanf(buffer, "%2[^.]. %c %d %d %.2f", &pStudents[i].ignore, &pStudents[i].Gender, &pStudents[i].Age, &pStudents[i].Height, &pStudents[i].Time) !=1)
{
printf("%d",&pStudents[i].Age);
fprintf(output,"%c",pStudents[i].Gender);
i++;
}
}
fclose(pInputFile);
fclose(output);
}
Thanks in advance !
UPDATE !!!
I am now having trouble with the next function
void calculateAverages(double *dAvHeight, double *dAvAge, double *dAvTime, Student_t *pStudents, int iNumberOfLines);
I can only define dAvHeight dAvAge dAvTime as Ints, however later on i need to change them to float to calculate averages. Can anyone explain how i do that while keep using dAvHeight dAvAge dAvTime.
Thanks again
Here is the updated code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int iNumberOfLines = 1;
int dAvHeight = 0, dAvAge = 0, dAvTime = 0;
typedef struct {
int ignore;
char Gender;
int Age;
int Height;
float Time;
} Student_t;
int determineNumberOfLines(FILE *pInputFile);
void readInputData(FILE *pInputFile, int iNumberOfLines, Student_t *pStudents);
void calculateAverages(double *dAvHeight, double *dAvAge, double *dAvTime, Student_t *pStudents, int iNumberOfLines);
// Student_t* searchFastest(Student_t *pStudents, int iNumberOfLines);
// void printToConsole(Student_t *pFastestStudent, double dAvHeight, double dAvAge, double dAvTime);
int main(int argc, char *argv[]) {
FILE *pInputFile = fopen ("resources/Input.txt", "r");
if (pInputFile == NULL){
printf("Fehler beim Öffnen");
return -1;
}
determineNumberOfLines(pInputFile);
//printf("LINES: %d\n",determineNumberOfLines(pInputFile));
Student_t pStudents[iNumberOfLines];
//printf("%d", iNumberOfLines);
readInputData(pInputFile, iNumberOfLines, pStudents);
calculateAverages(dAvHeight, dAvAge, dAvTime, pStudents, iNumberOfLines);
return 0;
}
int determineNumberOfLines(FILE *pInputFile){
fopen ("resources/Input.txt", "r");
int ch;
while(!feof(pInputFile))
{
ch = fgetc(pInputFile);
if(ch == '\n')
{
iNumberOfLines++;
}
}
fclose(pInputFile);
return iNumberOfLines;
}
void readInputData(FILE *pInputFile, int iNumberOfLines, Student_t *pStudents){
fopen ("resources/Input.txt", "r");
int i = 0;
char buffer [120];
while (fgets(buffer, sizeof buffer, pInputFile) != 0)
{
if (sscanf(buffer, "%d. %c %d %d %f", &pStudents[i].ignore, &pStudents[i].Gender, &pStudents[i].Age, &pStudents[i].Height, &pStudents[i].Time) <= sizeof buffer)
{
i++;
}
}
fclose(pInputFile);
}
void calculateAverages(double *dAvHeight, double *dAvAge, double *dAvTime, Student_t *pStudents, int iNumberOfLines){
int i;
int sumHeight = 0;
int sumAge = 0;
float sumTime = 0;
for (i = 0; i <= (iNumberOfLines-1); i++){
sumHeight = sumHeight + pStudents[i].Height;
}
dAvHeight = sumHeight/ iNumberOfLines;
printf("Average Height is = %.2f \n", dAvHeight);
for (i = 0; i<= (iNumberOfLines-1); i++){
sumAge = sumAge + pStudents[i].Age;
}
//dAvAge = sumAge/iNumberOfLines;
printf("Average Age is = %.2f \n", dAvAge);
for (i = 0; i<= (iNumberOfLines-1); i++){
sumTime = sumTime + pStudents[i].Time;
}
//dAvTime = sumTime/iNumberOfLines;
printf("Average Time is = %.2f \n", dAvTime);
}
nothing is being printed from the readInputData Function
You try to read something into memory pointed to by the uninitialized Student_t *pStudents. After you correctly determined iNumberOfLines, you can define Student_t pStudents[iNumberOfLines]; instead.
I found a lot of similar questions concerning this error, but the answers I found did not help me.
My program works for eleven data points which I read from a list "data.dat" without errors. If I increase the number of data points I get this error I don't understand. The file with my data consists of three columns of float numbers.
Here is a short version of my code.
#define DIM 3
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
// Recursive function to build tree
void my_function(FILE* outFile, double* r, int* idxList, unsigned long int* Nodes, int *node, int n, unsigned long int myKey)
{
unsigned long int myKey1 = myKey;
for(int q=0; q<8; q++)
{
fprintf(outFile, "%d %d %d\n", q, n, *node);
myKey1 = (myKey << 3)|q;
Nodes[*node] = myKey1;
*node += 1;
if(*node < 20)
{
my_function(outFile, r, idxList, Nodes, node, n, myKey1);
}
}
}
int main(int argv, char** argc)
{
FILE *inFile;
inFile = fopen("data.dat", "r");
FILE *outFile;
outFile = fopen("result.dat", "w");
unsigned int n = 15; // Number of points
unsigned int N = n*DIM; // Elements in array
// Array for points
double *r = NULL;
r = (double*)malloc(sizeof(double)*N);
unsigned long int *Nodes = NULL;
Nodes = (unsigned long int*)malloc(sizeof(unsigned long int)*3*n);
for(int i=0; i<3*n; i++)
{
Nodes[i] = 0b0;
}
int *idxList = NULL;
idxList = (int*)malloc(sizeof(int)*3*n);
memset(idxList, -1, sizeof(int)*3*n); // Set all entries to -1
for(int k=0; k<N; k++)
{
fscanf(inFile, "%lf", &r[k]);
}
int node = 0;
unsigned long int myKey = 0b1;
my_function(outFile, r, idxList, treeNodes, &node, n, myKey);
// Close files
fclose(inFile);
fclose(outFile);
// Clean up
free(r);
free(Nodes);
free(idxList);
}
The program works, but if I put more data points to the list, I get the following error.
*** Error in `./myProgram': munmap_chunk(): invalid pointer: 0x0000000000f74810
Aborted (core dumped)
If I comment the section
// Close files
fclose(inFile);
fclose(outFile);
// Clean up
free(r);
free(Nodes);
free(idxList);
of my code, the error disappears. How can I fix this error? Any suggestions?
I using first time the HEADERS in c so I'm not understanding it well.
main.c
#include <stdio.h>
#include <stdlib.h>
#include "kibe.h"
int main()
{
int a[5],n,i;
beolvas(a,n,"be.txt");
kiir(a,n);
return 0;
}
kibe.h
#ifndef KIBE_H_INCLUDED
#define KIBE_H_INCLUDED
void beolvas(int*, int, const char *);
void kiir(int*, int);
#endif // KIBE_H_INCLUDED
kibe.c
#include <stdio.h>
#include <stdlib.h>
void beolvas(int *a,int n,const char * file)
{
int i;
FILE * fin;
fin = fopen("be.txt", "rt");
fscanf(fin,"%i",&n);
a = (int*)malloc(n*sizeof(int));
for(i = 0; i < n; ++i){
fscanf(fin,"%i",&a[i]);
}
free(a);
}
void kiir(int *a,int n)
{
int i;
for(i = 0; i < n; ++i){
printf("%i ",a[i]);
}
}
The problem is that I get memory garbage every time and the file contains five numbers which must be read and written to monitor. If I write the void kiir is code to void beolvas function it works well.
You allocate dynamic memory in your function beolvas but you never pass it out of the function. Your parameters a and n have to be output parameters, so you have to change your function signature. Apart form this use fclos to close the file. Adapt your code like this:
kibe.c
void beolvas( int **a, int *n, const char * file )
// ^^ ^ output paramters a and n
{
FILE * fin;
fin = fopen("be.txt", "rt");
fscanf( fin, "%i", n ); // read number of elements
// ( n is a pointer to an int )
*a = malloc( *n * sizeof(int) ); // allocate memors
for ( int i = 0; i < n; ++i)
{
fscanf(fin,"%i",(*a)+i); // read one element
// ( *a is the pointer to the dynamic memory,
// so (*a)+i is a pointer to (*a)[i] )
}
fclose(fin);
}
kibe.h
void beolvas( int**, int* , const char *);
main.c
int main()
{
int a* = NULL;
int n = 0;
beolvas( &a, &n,"be.txt");
// ^ ^
kiir( a, n );
free(a); // free the memory which was allocated inside function beolvas
return 0;
}
I am trying to read 1 block of first hard drive into the memory. I tried with different LBAs but it loads spaces in to the buffer. In following code, i added for loop so that i can see if it loads anything else than just spaces. Do you guys know why it's only loading spaces into the buffer?
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
#include <bios.h>
struct DAP
{
unsigned char size;
unsigned char reserved1;
unsigned char blocks;
unsigned char reserved2;
unsigned char far *buffer;
unsigned long int lbalod;
unsigned long int lbahid;
} dap;
char st[80];
unsigned char buf[512];
FILE *fptr;
unsigned long int itrations = 16450559; //10gb
unsigned long int i = 0;
void main(void)
{
clrscr();
for(; i<itrations; i++)
{
dap.size = sizeof(dap);
dap.reserved1 = 0;
dap.blocks = 1;
dap.reserved2 = 0;
dap.buffer = (unsigned char far *)MK_FP(_DS, buf);
dap.lbalod = i;
dap.lbahid = 0;
_AH = 0x42;
_DL = 0x80;
_SI = (unsigned int)&dap;
geninterrupt(0x13);
printf("%lu: %s\n", i, buf);
}
}
It's using Borland Turbo C over VMWare virtual machine that is setup with WinXP. I have also tried the same on DOSBOX on Windows 7. Any help would be much appreciated.
These are only my suggestions in the hope that they help your debugging.
Print sizeof(dap) to ensure that it is indeed 16
Insert memset(buf, 'A', sizeof(buf)); before you issue INT 13h so that you can check buf is modified or not
Try printf("%lu: [%s]\n", i, buf); instead, because when buf contains \0 around its head printf stops there. The braces should work as marks.
Print _AH and _CF which should contain return codes of INT 13h
#include <dos.h>
#include <bios.h>
struct DAP
{
unsigned char size;
unsigned char reserved1;
unsigned char blocks;
unsigned char reserved2;
unsigned char far *buffer;
unsigned long int lbalod;
unsigned long int lbahid;
} dap;
char st[50];
unsigned char buff[256];
FILE *fptr;
main(void)
{
puts ("enter the lba low double word: ");
gets (st);
dap.lbalod=atol(st);
puts ("enter the lba high double word: ");
gets (st);
dap.lbahid=atol(st);
dap.size=16;
dap.reserved1=0;
dap.blocks1;
dap.reserved2=0
dap.buffer = (unsigned char far *)MK FP(DS.buf);
_AH = 0x42;
_DL = 0x80;
_SI = (unsigned int)%dap;
geninterrupt(0x13);
puts ("enter the path: ");
gets(st);
fptr = fopen(st, "wb");
fwrite(buf,256,1,fptr);
fclose(fptr);
}
i am getting statement missing error on this line dap.buffer = (unsigned char far *)MK_FP(_DS, buf);
Im making an application that uses of API-threads in C, The program takes N-files (N>2) with names disordered,per each file is generated a thread of execution which sort the files using the function qsort, after being ordered files, each thread should create a file keeping the original file intact and displaying the sorted file to another file with the extension <.sorted>. The program sorts the numbers without problems, even if I put standard output displays the result on screen, but when I try to create the output file with extension .sorted the program breaks out.
this is my code file.c
#include <stdio.h> /* Standard buffered input/output */
#include <stdlib.h> /* Standard library functions */
#include <string.h> /* String operations */
#include <pthread.h> /* Thread related functions */
#include "pf1.h" /* Header specific to this app */
pthread_attr_t attr;
void *thread_worker(void *name_file)
{
FILE *entrada, *salida;
char* nombres = (char*)name_file;
int numero;
char temp [10000];
int i;
stats_t estadisticas;
printf ("File_name:%s\n", nombres);
entrada = fopen(nombres, "r");
salida = fopen (strcat(nombres, ".sorted"), "w");
while (!feof(entrada)){
fscanf (entrada, "%s\n",temp);
numero++;
}
char* lista[numero]; //array to sort the file
rewind (entrada);
for (i=0;i<numero;i++)
{
fscanf(entrada," %[^\n]", temp);
lista[i] = (char*)malloc((strlen(temp)+1)*sizeof(char));
strcpy(lista[i], temp);
}
size_t large = sizeof(lista) / sizeof(char *);
qsort(lista,large ,sizeof(char *) ,cstring_cmp );
printf ("Archivo Ordenado\n", i+1);
for (i=0;i<large;i++)
printf("%s\n",lista[i]);
pthread_exit(NULL);
}
int main(int argc, char *argv [])
{
stats_t **stats;
int i, rc;
pthread_t my_threads[argc-1];
pthread_attr_init(&attr);
if (argc <3) {
printf ("|files| > 2\n");
}else{
printf("files to sorted: %d\n", argc - 1);
for (i = 1; i < argc; i++){
//printf("%s%s\n", argv[i], (i < argc-1) ? " " : "");
rc = pthread_create(&my_threads[i], &attr, thread_worker, (void *)argv[i]);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n",rc);
return -1;
}
}
}
return 0;
} /*end main */
this is mi file.h
#ifndef PF1_H_
#define PF1_H_
typedef struct _stats_t
{
char *longest, *shortest;
unsigned int numlines;
} stats_t;
int cstring_cmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return -strcasecmp(*ia, *ib);
/* strcmp functions works exactly as expected from
comparison function */
}
void print_cstring_array(char **array, size_t len)
{
size_t i;
for(i=0; i<len; i++)
printf("%s | ", array[i]);
putchar('\n');
}
#endif /* PF1_1_H_ */
I would like some help with this problem because I can not see which is the fault ... thanks to all in advance and excuse my English
This line here may be your problem:
salida = fopen (strcat(nombres, ".sorted"), "w");
From what I can tell, that nombres variable is coming from argv. Since you're not the one allocating memory for argv, you don't know that there will be extra space for the ".sorted" (and there probably won't be). If you strcpy it to your own buffer with space for the ".sorted", you should be fine.
#define EXT_LEN 7
#define MAX_TOTAL_LEN 250
#define MAX_FILE_LEN 242 //MAX_TOTAL_LEN - EXT_LEN - 1
char *name_ptr;
char nombres[MAX_TOTAL_LEN];
int len;
name_ptr = (char*)name_file;
len = strlen(name_ptr);
if (len > MAX_FILE_LEN) {
len = MAX_FILE_LEN;
}
strncpy(nombres, name_ptr, len);
strcpy(nombres+len, ".sorted");
salida = fopen (nombres, "w");
I once had issues about not passing an int identifier while calling thread execution functions. Try building a struct with both an integer identifier and the filename, then pass it as a parameter to your thread_worker() function.