Segmentation fault during fscanf()? - c

This is my beginner program experimentation with what I have learned on dynamic memory allocation, pointers, and files. Every time I compile I keep having a segmentation fault. I haven't been able to fix this error that occurs during fscanf().
#include <stdio.h>
#include <stdlib.h>
// create int aboveavg();
double average(int *ptr, int size){
int count = 0;
double sum = 0;
while(count <= size){
sum += *ptr;
ptr++;
count++;
}
sum /= size;
return sum;
}
int main(){
int n = 10;
int *ptr = (int*)calloc(n, sizeof(int)); //allocate dynamic memory
printf("Allocated %d integers\n", n);
FILE *input = fopen("a.txt" , "r"); //open file
if(input = NULL){ //error check
printf("Error! memory not allocated.");
exit(0);
}
int count = 0, i=0;
printf("check point\n");
while(fscanf(input, "%d", &ptr[i]) == 1){ //**Segmentation Fault**
if(count == n){
n *=2;
ptr = (int*)realloc(ptr,n* sizeof(int));
printf("Reallocated to %d integers\n", n);
}
i++;
count++;
}
fclose(input);
double avg = average(ptr, n);
printf("average of %f\n", avg);
free(ptr);
printf("Dynamic array freed\n");
return 0;
}
Searching for an answer (google or stack overflow), hasn't really helped me. Can anyone can hint/point to what I did wrong.

Related

Why doesn't my matrix store all my values? (C)

I am working on a problem in which i have to print out the reverse of the user-given words from the cmd. I also have to increase the allocated memory in case the number of inputs are greater than the originally given memory. Memory allocation and reallocation appear to be working fine. For some reason, my matrix only stores the last given input in all of its memory.
What is the problem? I even tried printing out the matrix cell values, but they are all filled with the last input.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** create_matrix(int cap);
char** matrix_reallocation(char** matrix, int* cap);
void free_matrix(char** matrix, int cap);
void print_reverse_matrix(char** matrix, int words);
int main(){
int cap = 8;
char** matrix = create_matrix(cap);
char tmp_word[1025];
int words = 0;
while (fscanf(stdin,"%s",tmp_word) != EOF){
matrix[words] = tmp_word;
words++;
printf("Words stored: %d, Capacity: %d\n", words, cap);
if (words == cap){
printf("Limit reached, reallocating....\n");
matrix = matrix_reallocation(matrix, &cap);
}
}
//printf("%s", matrix[0]);
//printf("%s", matrix[1]);
//printf("%s", matrix[2]);
//printf("%s", matrix[3]);
print_reverse_matrix(matrix,words);
free_matrix(matrix,cap);
return 0;
}
char** create_matrix(int cap){
char** matrix = malloc(sizeof(char*) * cap);
for (int i = 0; i < cap; ++i)
{
matrix[i] = malloc(sizeof(char*) * 1025);
if (matrix[i] == NULL){
printf("Memory allocation failed\n");
exit(1);
}
}
return matrix;
}
char** matrix_reallocation(char** matrix, int *cap){
char** new_matrix = realloc(matrix, sizeof(char*) * *cap * 2);
printf("1D reallocated\n");
*cap *= 2;
printf("Capacity increased\n");
for (int i = (*cap/2); i < *cap; ++i)
{
new_matrix[i] = malloc(sizeof(char*) * 1025);
if (new_matrix[i] == NULL){
printf("Memory allocation failed\n");
exit(1);
}
}
printf("Succesful reallocation, new capacity: %d\n", *cap);
return new_matrix;
}
void print_reverse_matrix(char** matrix, int words){
for (int i = (words - 1); i >= 0 ; i--)
{
printf("%d ", i+1);
for (int j = (strlen(matrix[i]) - 1); j >= 0 ; j--)
{
printf("%c ", matrix[i][j]);
}
printf("\n");
}
}
void free_matrix(char** matrix, int cap){
for (int i = 0; i < cap; ++i)
{
free(matrix[i]);
}
free(matrix);
}
In each iteration of the loop you overwrite tmp_word and then assign a row in the matrix to it, making them all point to the same string. Instead, you should copy it to the matrix:
char tmp_word[1025];
int words = 0;
while (fscanf(stdin,"%s",tmp_word) != EOF){
strcpy(matric[words], tmp_word); /* Here! */
words++;
printf("Words stored: %d, Capacity: %d\n", words, cap);
if (words == cap){
printf("Limit reached, reallocating....\n");
matrix = matrix_reallocation(matrix, &cap);
}
}

Dynamically allocated int Array in C input via terminal

I am new to C and I was trying to code up a dynamic int array that lets the user type in numbers via terminal untill the user types in -1. So the user can type any amount of int's and the data is reallocated each time another valid int is input.
Sometimes it works as expected other times I get: free(): double free detected in tcache 2
Aborted (core dumped) error.
I am printing the values after every input and everything seems fine untill -1 is input. And the bug only occures every other time.
Here is my Code:
void output(int *ptr, int len){
printf("\n");
for(int i=0; i<len; i++){
printf("%d %p \n", ptr[i], ptr+i);
}
printf("\n");
}
int input(int *ptr, int *size){
int x;
printf("Insert your numbers:\n");
while(1){
scanf("%d", &x);
if(x == -1) break;
size[0]++;
// printf("Size: %d\n", size[0]);
ptr = realloc(ptr, size[0] * sizeof(int));
if(ptr == NULL) return -1;
int indexToStore = size[0]-1;
// printf("Index: %d\n", indexToStore);
ptr[indexToStore] = x;
output(ptr, size[0]);
}
return 0;
}
int main()
{
int size = 0;
int *array = (int*)malloc(sizeof(int));
if(array == NULL) return -1;
input(array, &size);
output(array, size);
input(array, &size);
output(array, size);
free(array); array = NULL;
return 0;
}
The argument ptr of the function input is a copy of what is passed and modifying that will not affect what is passed in caller.
Therefore, the change in buffer via realloc() is not saved from the 1st call of input() to the 2nd call of input() and it will lead to troubles.
You should pass a pointer to what should be modified to have functions modify caller's local things.
#include <stdio.h>
#include <stdlib.h>
void output(int *ptr, int len){
printf("\n");
for(int i=0; i<len; i++){
printf("%d %p \n", ptr[i], ptr+i);
}
printf("\n");
}
int input(int **ptr, int *size){
int x;
printf("Insert your numbers:\n");
while(1){
scanf("%d", &x);
if(x == -1) break;
size[0]++;
// printf("Size: %d\n", size[0]);
*ptr = realloc(*ptr, size[0] * sizeof(int));
if(*ptr == NULL) return -1;
int indexToStore = size[0]-1;
// printf("Index: %d\n", indexToStore);
(*ptr)[indexToStore] = x;
output(*ptr, size[0]);
}
return 0;
}
int main()
{
int size = 0;
int *array = (int*)malloc(sizeof(int));
if(array == NULL) return -1;
input(&array, &size);
output(array, size);
input(&array, &size);
output(array, size);
free(array); array = NULL;
return 0;
}

C fork and pipe add numbers from a file

Totals different for same file when executed.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_FILE_NAME 100
#define RUNS 1
int main() {
int num,i;
FILE *fp;
char*s, buf[1024];
int count =0;
char c;
char filename[MAX_FILE_NAME];
printf("Enter filename: ");
scanf ("%s",filename);
if ((fp =fopen(filename, "r")) == NULL) {
printf("Error");
exit(1);
}
fscanf(fp,"%d",&num);
for (c = getc(fp); c!= EOF; c = getc(fp))
{
if (c == '\n'){
count = count+1;
}
}
printf("%s has %d numbers \n", filename, count);
int f;
printf("Choose from the options how many processes you want to use [1,2,4]: ");
scanf("%i", &f);
printf("%i processes \n", f);
int fds[f+1][2];
int numb[count];
int x,k;
time_t start, finish;
start = time(NULL);
for(i = 0; i < RUNS; i++)
{
pipe(fds[f]);
for( x = 0; x<f; x++)
{
pipe(fds[x]);
int ind[2];
ind[0] = ((x)*(count/f));
ind[1] = ((x+1)*(count/f));
write(fds[x][1], &ind, 2* sizeof(int));
if (fork() ==0)
{
int t =0;
int ind2[2];
read(fds[x][0], &ind2, 2*sizeof(int));
for( k = ind2[0]; k<ind2[1]; k++)
{
t += numb[k];
}
write(fds[f][1], &t, sizeof(int));
exit(0);
}
}
int m, tmp, total;
total = 0;
for( m = 0; m < f; m++)
{
for( m = 0; m < f; m++)
{
read(fds[f][0], &tmp, sizeof(int));
sleep(5);
total += tmp;
}
printf("DOne calc \n");
printf("Total: %i \n", total);
}
finish = time(NULL);
float runtime = (float)((finish-start)/RUNS);
printf("runtime: %f \n", runtime);
fclose(fp);
return 0;
}
You get random result for the same input because the calculation based on uninitialized int numb[count]; values.
According to the C99 standard, section 6.7.8.10:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.
Because of it int numb[count]; contains some random junk from memory. To get predictive results use explicit initialization:
#include <string.h> // memset
int numb[count];
memset (numb, 0, sizeof(numb)); // Zero-fills
Use the code bellow to put numbers from filename file into numb:
int i = 0;
char line[1024];
fseek(fp, 0, SEEK_SET);
while(fgets(line, sizeof(line), fp) )
{
if( sscanf(line, "%d", &numb[i]) == 1 ) // One number per line
{
++i;
}
}

How can I create a dynamic array in a procedure in C?

I'm new to this fantastic site and I found it very useful in many occasions, but now I'm dealing with a problem which I can't seem to solve.
I'm a beginner C student and I'm studying dynamic memory allocation.
I want to create a dynamic array of, let's say, integers, allocating memory for it inside a procedure, not in the main function.
This works:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *numbers; // pointer to create a dynamic array
int *test; // pointer to test realloc function
int c;
size_t i = 0;
unsigned int dim; // array's length
// allocate memory for the 1st number
numbers = malloc(sizeof(*numbers));
if (numbers == NULL) {
fputs("Error while allocating memory!\n", stderr);
} else {
printf("Insert the 1 number: ");
scanf("%d", &numbers[0]);
++i;
/* allocate memory for the other numbers,
* until the user inputs EOF
*/
while (!feof(stdin)) {
test = realloc(numbers, (sizeof(*numbers) * (i + 1)));
if (test == NULL) {
fputs("Error while allocating memory!\n", stderr);
} else {
numbers = test;
printf("Insert the %u number: ", i + 1);
scanf("%d", &numbers[i]);
++i;
}
}
dim = --i;
// print the array, 5 numbers per line
for (i = 0; i < dim; ++i) {
if (i % 5 == 0) {
puts("");
}
printf("%d ", numbers[i]);
}
puts("");
}
getchar();
return 0;
}
But I want to do this (which doesn't work):
#include <stdio.h>
#include <stdlib.h>
void get_numbers(int **numbers, unsigned int *dim);
int main()
{
int *numbers; // pointer to create a dynamic array
size_t i = 0;
unsigned int dim; // array's length
get_numbers(&numbers, &dim);
// print the array, 5 numbers per line
for (i = 0; i < dim; ++i) {
if (i % 5 == 0) {
puts("");
}
printf("%d ", numbers[i]);
}
puts("");
getchar();
return 0;
}
void get_numbers(int **numbers, unsigned int *dim)
{
int *test; // pointer to test realloc function
int c;
size_t i = 0;
// allocate memory for the 1st number
*numbers = malloc(sizeof(*numbers));
if (*numbers == NULL) {
fputs("Error while allocating memory!\n", stderr);
} else {
printf("Insert the 1 number: ");
scanf("%d", &numbers[0]); // Maybe the error is here
++i;
/* allocate memory for the other numbers,
* until the user inputs EOF
*/
while (!feof(stdin)) {
test = realloc(*numbers, (sizeof(*numbers) * (i + 1)));
if (test == NULL) {
fputs("Error while allocating memory!\n", stderr);
} else {
*numbers = test;
printf("Insert the %u number: ", i + 1);
scanf("%d", &numbers[i]);
++i;
}
}
*dim = --i;
}
}
Do I need to use a pointer to a pointer to int, right?
I know I made some mistakes but I can't figure out how to fix them.
Thanks in advance for your replies!
Bye,
Fabio Nardelli
In the first block of code, numbers is of type int*.
In the second block of code, numbers is of type int**.
You have not fixed all the places that need to be fixed because of that change.
My suggestion:
Change the input argument to numbersPtr.
Create a local variable int* numbers.
Before you return from the function, set *numbersPtr to number.
void get_numbers(int **numbersPtr, unsigned int *dim)
{
int* numbers;
...
*numbersPtr = numbers;
}
It will be better to change get_numbers to return numbers.
int* get_numbers(unsigned int *dim)
{
int* numbers;
...
return numbers;
}
and change its usage as:
numbers = get_numbers(&dim);

Help with scanf and memory allocation

Here is my code:
#include <stdio.h>
#include <stdlib.h>
#define MAX 50
float** getdata(void);
void calculations(float* fPtr);
//void printoriginal(float* values, int inputnum, float* fPtr);
int main(void)
{
float** fPtr;
float* values;
fPtr = getdata();
calculations(*fPtr);
int element;
// printoriginal(*values, inputnum, *fPtr);
system("PAUSE");
return 0;
}
float getvalues(void)
{
float* values = (float*)calloc(*inputnum, sizeof(float));
float** getdata(void)
{
int i;
int n;
float** fPtr;
int* inputnum;
printf("How many values do you want to input into the array?");
scanf("%d", inputnum);
float* values = (float*)calloc(*inputnum, sizeof(float));
if (values == NULL)
{ printf("Memory overflow\n");
exit(101);
}
for(i = 0; i < *inputnum; i++)
{
n = i + 1;
printf("Please enter your %d number: ", n);
scanf("%f",(values+i));
}
fPtr = (float**)calloc(*inputnum+1, sizeof(float*));
if (fPtr == NULL)
{ printf("Memory overflow\n");
exit(101);
}
for(int c=0; c < *inputnum; c++)
{
*(fPtr+i) = (values+i);
}
printf("%f", values+2);
return fPtr;
}
I scanf the values in getdata, but I am scanning in garbage. Im pretty certain my scanf is off. Also, how would I be able to pass back my values array through reference?? I am having a very hard time with that as well. Thanks everyone.
Instead of
int * inputnum;
scanf( ..., inputnum );
you want:
int inputnum;
scanf( ..., &inputnum );
Either that, or you need to insert an allocation of inputnum:
/* Very non-C-worthy code sample */
int * inputnum;
inputnum = malloc( sizeof *inputnum );
if( inputnum == NULL ) {
perror( "malloc" );
exit( EXIT_FAILURE );
}
scanf( ..., inputnum );
but that will look very strange to anyone familiar with C
(Unless there is some other reason for it, and in this
case there does not appear to be any reason.)
The problem you are experiencing is that the scanf is
storing the received value in the location pointed to
by inputnum, which is a bogus location since inputnum
is uninitialized.
I like to have objects "assigned" to one single function. In your program, your values are created in the function getdata(), used in calculations() and never released.
If the main() function was responsible for them, it would make coding easier, in my opinion. Something like
int main(void) {
int inputnum, innum;
double *fPtr;
printf("How many values do you want to input into the array?");
fflush(stdout);
if (scanf("%d", &inputnum) != 1) {
fprintf(stderr, "Error in input. Program aborted.\n");
exit(EXIT_FAILURE);
}
if (inputnum > MAX) { /* ... nothing yet ... */ }
fPtr = calloc(inputnum, sizeof *fPtr);
if (fPtr == NULL) {
fprintf(stderr, "Not enough memory. Program aborted.\n");
exit(EXIT_FAILURE);
}
/* use fPtr in other functions */
innum = data_get(fPtr, inputnum);
data_print(fPtr, innum);
free(fPtr);
return 0;
}
In the snippet above, I used the functions data_get() and data_print() with a somewhat different prototype than you have. These functions take a pointer and a number of elements.
int data_get(double *data, int num);
void data_print(double *data, int num);
The first one reads up to num doubles into the memory pointed to by data and returns the number of doubles that was effectively entered.
The second takes number of doubles to print.
Oh! Unless you have a very good reason to use floats, don't use them. Always prefer doubles.
Also Instead of
printf("%f", values+2);
use
printf("%f", *(values+2));
There is so many errors, I didn't know where to start :)
Code completely rewritten below. Please study this.
#include <stdio.h>
#include <stdlib.h>
#define MAX 50
int get_data (float** array); /* must be pointer-to-pointer to return through parameter */
void print_data (const float* array, int size); /* print data */
void do_weird_things (float* array, int size); /* do weird things with the data */
void clear_data (float* array); /* clean up */
int main(void)
{
float* array;
int size;
size = get_data (&array);
printf("Before weird things:\n");
print_data (array, size);
do_weird_things (array, size);
printf("After weird things:\n");
print_data (array, size);
clear_data (array);
system("PAUSE");
return 0;
}
int get_data (float** array)
{
int i;
int items;
printf("How many values do you want to input into the array? ");
scanf("%d", &items);
getchar(); /* remove \n from stdin */
*array = calloc(items, sizeof(float));
if (*array == NULL)
{
printf("Memory overflow\n");
exit(EXIT_FAILURE);
}
for(i = 0; i < items; i++)
{
printf("Please enter your %d number: ", i+1);
scanf("%f", (*array) + i);
getchar(); /* remove \n from stdin */
}
return items;
}
void do_weird_things (float* array, int size) /* do whatever data manipulation you wish here */
{
int i;
for(i=0; i<size; i++)
{
array[i] += i;
}
}
void print_data (const float* array, int size)
{
int i;
for(i=0; i<size; i++)
{
printf("%f\t", array[i]);
}
printf("\n");
}
void clear_data (float* array)
{
free(array);
}

Resources