I am trying to get data from a .tsv4 file. Whenever the code is run it returns with a segmentation fault: 11. The goal of the code is to store the unknown numbers into an array without knowing the amount of numbers in the file. The file I'm trying to access has 92 float values, and it stores them properly. But it will still give the segmentation fault error. I know this is because of a memory issue, just unsure of how to handle it
The file seems to get the segmentation fault from line 24
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int getFileInfo(const char *filename, float list[]);
int main(void)
{
float list[] = {0};
int size = getFileInfo("numbers.tsv4",list);
return 0;
}
int getFileInfo(const char *filename, float list[])
{
FILE* spData;
if((spData = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "Error opening file %s.\n",filename);
exit(1);
}
int i = 0;
while(fscanf(spData, "%f", &list[i]) != EOF)
{
i++;
}
if (fclose(spData) == EOF)
{
fprintf(stderr, "Error closing file %s.\n", filename);
exit(2);
}
return i + 1;
}
The goal of the code is to store the unknown numbers into an array
without knowing the amount of numbers in the file
In order to this read floats one by one and allocate the array on the heap.
When you write
float list[] = {0};
int size = getFileInfo("numbers.tsv4",list);
you allocate an array with one value on the stack and that can never change.
Instead pass a pointer to the function and let the function manipulate that pointer
float* list = NULL;
int size = getFileInfo("numbers.tsv4",&list);
Inside your function read the float values from the file and as the need increases realloc the list array E.g.
int size = 10; // lets start with 10 values
int readFloats = 0; // number of floats read
*list = malloc(sizeof(float)*size);
...
if (readFloats > size)
{
float* tmp = realloc(*list, sizeof(float)*(size+10));
if ( tmp != NULL )
{
size += 10;
*list = tmp;
}
... put in the float
}
At the end realloc again with the current number of floats to get the right size
tmp = realloc(*list, readCurrent*sizeof(float));
if ( tmp != NULL )
{
size = readCurrent;
*list = tmp;
}
...
Related
I'm trying to teach C to myself and I'm struggling with what it looks like a very basic thing. I have a struct with a char pointer and I want to dynamically allocate memory and free it once done. What I understand is that I need to allocate memory for both the struct and the char pointer but it looks like I'm missing something because I'm getting a Segmentation fault on the sprintf line.
As an exercise to understand and use malloc and free, I'm trying to build an easy program that takes an int as input and outputs a table with the factorials of all the numbers from 0 to input. Each table entry has its index (int), the result of the factorial (long long int) and the result but in an array of chars format (this is the problematic one).
Here's what I have until now:
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define LIMIT 20
struct entry
{ /* Definition of each table entry */
int n;
long long int lli;
char *str;
};
void shout(char *m)
{
fprintf (stderr, "%s\n", m);
exit (0);
}
int main (int argc, char *argv[])
{
int n;
int i;
struct entry *fact_table;
if (argc != 2)
shout("wrong parameters");
n = atoi (argv[1]);
if (n < 0)
shout("n too small");
if (n > LIMIT)
shout("n too big");
// Allocate memory for struct
fact_table = (struct entry*) malloc((n+1) * sizeof(struct entry));
if (fact_table == NULL) {
shout("malloc");
}
// Compute factorials
fact_table[0].n = 0;
fact_table[0].lli = fact_table[1].n = fact_table[1].lli = 1; // 0! = 1! = 1
fact_table[0].str = fact_table[1].str = "1";
for (i=2; i<=n; i++) {
fact_table[i].n = i;
fact_table[i].lli = i * fact_table[i-1].lli; // N! = N*(N-1)!
int digits = log10(fact_table[i].lli) + 1; // get number of digits of the result to allocate memory in consequence
fact_table[i].str = malloc((digits + 1)*sizeof(char));
if (fact_table[i].str = NULL) {
shout("malloc");
}
sprintf(fact_table[i].str, "%lld", fact_table[i].lli); // convert to string. ERROR HERE
}
// print factorial table
for (i= 0; i<=n; i++)
{
printf ("%d %lld %s\n", fact_table[i].n, fact_table[i].lli, fact_table[i].str);
}
// Free memory
for (i=0; i<=n; i++) {
free(fact_table[i].str);
}
free(fact_table);
return 0;
}
I'm probably missing something very obvious and making a silly mistake when allocating the memory for the fact_table[i].str, but I'm struggling to make it work.
In addition to the comments about freeing the memory for n >= 2, if you look at your test after the malloc:
if (fact_table[i].str = NULL) {
You are setting your pointer to NULL. Instead you should write:
fact_table[i].str = malloc((digits + 1)*sizeof(char));
if ( fact_table[i].str == NULL) {
shout("malloc");
}
Just some little recommendation here. This mistake generates a warning on most compiler if you compile using -Wall:
fact.c: In function ‘main’:
fact.c:53:9: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if (fact_table[i].str = NULL) {
^~~~~~~~~~
Also, in order to make sure the compiler will complain if you forget a =, you can compare the values of a variable and of a constant placing the constant on the left: if you write if (NULL = fact_table[i].str), your compiler will complain and notify you with the error.
I reproduced this issue on my setup. We need to fix two issues before program runs ok.
change 'fact_table[i].str = NULL' to 'fact_table[i].str == NULL'. Your previous command directly set 'str' to NULL, which is not expected. This is the reason you met segment error.
In Free memory part, you need to start from index 2. You cannot free memory which doesnot belong to you.
Below code can work well in my setup.
Wish this can help you.
**
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define LIMIT 20
struct entry
{ /* Definition of each table entry */
int n;
long long int lli;
char *str;
};
void shout(char *m)
{
fprintf (stderr, "%s\n", m);
exit (0);
}
int main (int argc, char *argv[])
{
int n;
int i;
struct entry *fact_table;
if (argc != 2)
shout("wrong parameters");
n = atoi (argv[1]);
if (n < 0)
shout("n too small");
if (n > LIMIT)
shout("n too big");
// Allocate memory for struct
fact_table = (struct entry*) malloc((n+1) * sizeof(struct entry));
if (fact_table == NULL) {
shout("malloc");
}
// Compute factorials
fact_table[0].n = 0;
fact_table[0].lli = fact_table[1].n = fact_table[1].lli = 1; // 0! = 1! = 1
fact_table[0].str = fact_table[1].str = "1";
for (i=2; i<=n; i++) {
fact_table[i].n = i;
fact_table[i].lli = i * fact_table[i-1].lli; // N! = N*(N-1)!
int digits = log10(fact_table[i].lli) + 1; // get number of digits of the result to allocate memory in consequence
fact_table[i].str = malloc((digits + 1)*sizeof(char));
if (fact_table[i].str == NULL) {
shout("malloc");
}
sprintf(fact_table[i].str, "%lld", fact_table[i].lli); // convert to string. ERROR HERE
}
// print factorial table
for (i= 0; i<=n; i++)
{
printf ("%d %lld %s\n", fact_table[i].n, fact_table[i].lli, fact_table[i].str);
}
// Free memory
for (i=2; i<=n; i++) {
free(fact_table[i].str);
}
free(fact_table);
return 0;
}
**
I am trying to create a 2d array dynamically, then open a txt file and copy each lenient my 2d array. Then save this array back to my main. I keep running into a segmentation error. Any suggestions how to do fix this code?
BTW i think the problem stars after the 2nd time while loop occurs...
#include<stdio.h>
char **randomArrayofStrings(){
char **twoArray=null;
int rows=50;
int col=20;
i=0;
FILE *file=null;
int messageSize=50;//this is number is trivial
file = fopen("somefile.txt","r");
twoArray= malloc(rows*sizeof(char*));
for(i=0;i<col;i++)
{
twoArray[i]=malloc(rows*sizeof(char));
strcpy(twoArray[i], "some random word");
}
while(!feof(file))
{
fgets(dArray[i],messageSize, file);
strtok(dArray[i], "\n");
i++;
}
return twoArray;
}
int main(int argc, char **argv)
{
char **localArray=null;
localArray=randomArrayofStrings();
for(i=0;i<20;i++)//20 is just a random number
printf("Strings: %s", localArray[i]);
}
As I see, in your function randomArrayofStrings loop for goes through columns "i cols in your code. So, you allocate array of pointers first and consider it as cols and then in a loop you allocate rows.
And after malloc check the value that was returned and do not use the pointer if it is NULL after memory allocation.
To free allocated memory, use the inverted sequence - free all rows in a loop and than free cols once. E.g.:
for(i=0;i<col;i++){
free(twoArray[i]);
}
free(twoArray);
twoArray = NULL;
EDIT:
And also, to use malloc and free you need #include <stdlib.h>, and #include <string.h> for strcopy, int i=0; should be instead of i=0;, and correct null value for pointers is NULL.
And what is dArray? I do not see the declaration or definition? Dou you mean twoArray?
EDIT2:
The following is my version of your program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **randomArrayofStrings(){
char **twoArray=NULL;
char * ptr = NULL;
int rows=50; // this will be also message size
int cols=20;
int i=0;
FILE *file=NULL;
file = fopen("somefile.txt","r");
if( file == NULL )
return NULL;
twoArray = (char**) malloc(cols * sizeof(char*));
if(twoArray == NULL)
{
return NULL;
}
for(i=0;i<cols;i++)
{
twoArray[i] = (char*)malloc(rows*sizeof(char));
if(twoArray[i] == NULL)
return NULL;
strcpy(twoArray[i], "some random word");
}
i = 0; // reset counter
while(!feof(file))
{
fgets(twoArray[i], rows, file);
ptr = strchr(twoArray[i],'\n');
if( ptr )
*ptr = '\0';
else
twoArray[i][rows-1] = '\0';
i++;
if( i >= cols)
break;
}
fclose(file);
return twoArray;
}
void freeMy2dArray(char **twoArray, int n)
{
int i;
for(i=0; i < n; i++){
free(twoArray[i]);
}
free(twoArray);
twoArray = NULL;
}
int main(int argc, char **argv)
{
int i;
char **localArray=NULL;
localArray = randomArrayofStrings();
if( localArray == NULL )
return 1;
for(i=0;i<20;i++)//20 is just a random number
printf("Strings: %s\n", localArray[i]);
freeMy2dArray(localArray, 20);
}
You are not suppossed to free() twoArray inside randomArrayofStrings(). You have to free them inside main(), once you're done with using the allocated memeory.
That said, the way you're using sizeof(localArray) in main() is wrong. You have to use the exact value you did use to poupulate twoArray.
i have a problem with the initialization of the values inside the first dynamic array of pointers
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char*** GetIndexes()
{
int n = 0;
char ***index;
printf("please insert the number of words you want to add to dictionary\n");
scanf("%d", &n);
index = (char***)calloc(n, sizeof(char));
if (index == NULL)
{
printf("allocation Failed");
return;
}
return index;
}
char** GetDefinitions()
{
int n = 0;
char **definition;
printf("please insert the number of defintions you want to add to the word\n");
scanf("%d", &n);
definition = (char**)calloc(n+1, sizeof(char));
if (definition == NULL)
{
printf("allocation failed");
return;
}
return definition;
}
int main()
{
char *** dptr = GetIndexes();
if (dptr == NULL)
{
printf("memory Allocation failed");
}
int indexcount = sizeof(dptr) / sizeof(char),i;
for (i = 0; i < indexcount; i++)
{
printf("word number %d\n", i + 1);
*dptr[i] = GetDefinitions();
}
printf("%p",dptr);
}
i tried running the debugger in VS2013 and after i enter the number of defintions i want it crashed with this message:
Unhandled exception at 0x01103FB0 in ConsoleApplication1.exe: 0xC0000005: Access violation writing location 0x00000000.
i missed an allocation of something but i cant quite figure out what i missed,
thanks in advance
Your program is very broken
You allocate n char ***s but only request space for n chars and also do it for char **, to prevent this kind of mistake you may use the sizeof operator this way
char ***index;
index = calloc(n, sizeof(*index));
and
char **definition;
definition = calloc(n, sizeof(*definition));
and as you see casting calloc makes it harder and it's not necessary.
You have a return statement that doesn't return anything an GetIndexes() as well as one in GetDefinitions.
They should return NULL if you want to handle failure in the caller function
return NULL;
You erroneously use the sizeof operator to determine the number of char *** pointer allocated in
int indexcount = sizeof(dptr) / sizeof(char)
this will be either 4 or 8 depending on the architecture i.e. the size of a pointer divided by 1 sizeof(char) == 1 always.
You can't compute that value, you simply have to keep track of it. The size
You dereference the triple pointer twice and try to assign a double pointer to it
*dptr[i] = GetDefinitions();
here the operator precedence is also an issue, but regardless of that, this is wrong, may be what you meant was
dptr[i] = GetDefinitions();
This is not going to make your program crash, but it's certainly important to free all malloced pointers before exiting the program.
Here is a suggestion for your code to work, ignore it's purpose since it's not clear what you are trying to do
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char ***GetIndexes(unsigned int *count)
{
char ***index;
printf("please insert the number of words you want to add to dictionary > ");
scanf("%u", count);
index = calloc(*count, sizeof(*index));
if (index == NULL)
{
printf("allocation Failed");
return NULL;
}
return index;
}
char **GetDefinitions(unsigned int *count)
{
char **definition;
printf("please insert the number of defintions you want to add to the word > ");
scanf("%u", count);
definition = calloc(*count + 1, sizeof(*definition));
if (definition == NULL)
{
printf("allocation failed");
return NULL;
}
return definition;
}
int main()
{
unsigned int indexCount, i;
char ***dptr = GetIndexes(&indexCount);
if (dptr == NULL)
{
printf("memory Allocation failed");
}
for (i = 0; i < indexCount; i++)
{
unsigned int definitionsCount;
printf("Word number %u\n", i + 1);
dptr[i] = GetDefinitions(&definitionsCount);
if (dptr[i] != NULL)
{
/* use dptr[i] here or maybe somewhere else, but when you finish */
free(dptr[i]);
}
}
printf("%p", dptr);
/* now if you are done using dptr */
free(dptr);
return 0;
}
As already mentioned in the comment this is a very bad idea and just using double pointers is good here. But the below fixes should be done if you want to use pointers to allocate memory
index = calloc(n, sizeof(char));
should be
index = calloc(n, sizeof(char **));
and
definition = calloc(n+1, sizeof(char));
should be
definition = calloc(n+1, sizeof(char *));
I've got a function which, as is, works correctly. However the rest of the program has a limitation in that I've preset the size of the array (the space to be allocated). Obviously, this is problematic should an event arise in which I need extra space for that array. So I want to add dynamic allocation of memory into my program.
But I'm having an issue with the whole pointer to a pointer concept, and I've utterly failed to find an online explanation that makes sense to me...
I think I'll want to use malloc(iRead + 1) to get an array of the right size, but I'm not sure what that should be assigned to... *array? **array? I'm not at all sure.
And I'm also not clear on my while loops. &array[iRead] will no longer work, and I'm not sure how to get a hold of the elements in the array when there's a pointer to a pointer involved.
Can anyone point (heh pointer pun) me in the right direction?
I can think of the following approaches.
First approach
Make two passes through the file.
In the first pass, read the numbers and discard them but keep counting the number of items.
Allocate memory once for all the items.
Rewind the file and make a second pass through it. In the second pass, read and store the numbers.
int getNumberOfItems(FILE* fp, int hexi)
{
int numItems = 0;
int number;
char const* format = (hexi == 0) ? "%X" : "%d";
while (fscanf(fp, format, &number) > 0) {
++numItems;
return numItems;
}
void read(int *array, FILE* fp, int numItems, int hexi)
{
int i = 0;
char const* format = (hexi == 0) ? "%X" : "%d";
for ( i = 0; i < numItems; ++i )
fscanf(fp, format, &array[i]);
}
int main(int argc, char** argv)
{
int hexi = 0;
FILE* fp = fopen(argv[1], "r");
// if ( fp == NULL )
// Add error checking code
// Get the number of items in the file.
int numItems = getNumberOfItems(fp, hexi);
// Allocate memory for the items.
int* array = malloc(sizeof(int)*numItems);
// Rewind the file before reading the data
frewind(fp);
// Read the data.
read(array, fp, numItems, hexi);
// Use the data
// ...
// ...
// Dealloate memory
free(array);
}
Second approach.
Keep reading numbers from the file.
Every time you read a number, use realloc to allocate space the additional item.
Store the in the reallocated memory.
int read(int **array, char* fpin, int hexi)
{
int number;
int iRead = 0;
// Local variable for ease of use.
int* arr = NULL;
char const* format = (hexi == 0) ? "%X" : "%d";
FILE *fp = fopen(fpin, "r");
if (NULL == fp){
printf("File open error!\n");
exit(-1);
}
while (fscanf(fp, format, &number) > 0) {
arr = realloc(arr, sizeof(int)*(iRead+1));
arr[iRead] = number;
iRead += 1;
}
fclose(fp);
// Return the array in the output argument.
*array = arr;
return iRead;
}
int main(int argc, char** argv)
{
int hexi = 0;
int* array = NULL;
// Read the data.
int numItems = read(&array, argv[1], hexi);
// Use the data
// ...
// ...
// Dealloate memory
free(array);
}
int read(int **array, char* fpin, int hexi) {
int iRead = 0;
int i, *ary;
char *para;
FILE *fp;
fp = fopen(fpin, "r");
if (NULL == fp){
printf("File open error!\n");
exit(-1);
}
para = (hexi == 0) ? "%*X" : "%*d";
while (fscanf(fp, para)!= EOF)
++iRead;
ary = *array = malloc(iRead*sizeof(int));
if(ary == NULL){
printf("malloc error!\n");
exit(-2);
}
rewind(fp);
para = (hexi == 0) ? "%X" : "%d";
for(i = 0; i < iRead; ++i)
fscanf(fp, para, &ary[i]);
fclose(fp);
return iRead;
}
I'd suggest something like this:
int read(int **array_pp, char* fpin, int hexi) {
...
int *array = malloc (sizeof (int) * n);
for (int i=0; i < n; i++)
fscanf(fp, "%X",&array[i]);
...
*array_pp = array;
return n;
}
Notes:
1) You must use "**" if you want to return a pointer in a function argument
2) If you prefer, however, you can declare two pointer variables (array_pp and array) to simplify your code.
I think you wouldn't call it an array. Arrays are of fixed size and lie on the stack. What you need (as you already said), is dynamically allocated memory on the heap.
maybe that's why you didn't find much :)
here are some tutorials:
http://en.wikibooks.org/wiki/C_Programming/Arrays (and following pages)
http://www.eskimo.com/~scs/cclass/int/sx8.html
you got the function declaration correctly:
int read(int **array, char* fpin, int hexi)
What you need to do:
find out how much memory you need, eg. how many elements
allocate it with *array = malloc(numElements * sizeof(int)) (read "at the address pointed by array allocate memory for numElements ints")
now you can (*array)[idx] = some int (read "at the address pointed by array, take the element with index idx and assign some int to it")
call it with int* destination; int size = read(&destination, "asdf", hexi)
hope it helps..
I am learning pointer in c
i have written a small program , but i am getting segmentaion fault
i dont know where i am having the issue
please let me know the issue with the code , it is an array of pointers to string ,
which is in a pointer to structure .
# include <stdio.h>
#include <stdlib.h>
# include <string.h>
char *sum(char **sol) ;
char *summer_sum(char*** solcs) ;
int main()
{
char* datum ="teststring";
sum(&datum);
}
char *sum(char** sol)
{
printf("\n value is : %s",*sol);
summer_sum(&sol);
return "1" ;
}
char *summer_sum(char*** solcs)
{
int i=0;
typedef struct
{
char *asg[40];
}nlist;
nlist *n1;
for( i=0 ; i<= 38 ;i++)
{
n1->asg[i] = calloc(1,1*sizeof(*solcs));
strcpy(n1->asg[i],**solcs);
printf("\n %d value is : %s",i,n1->asg[i]);
}
return NULL;
}
n1 is used uninitialized:
n1->asg[i] = calloc(1,1*sizeof(*solcs));
On the other hand, if you want to allocate enough space for the use of strcpy, you must use strlen instead of sizeof
And you don't need a double or triple pointer, your code simplified:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void sum(char *sol);
char *summer_sum(char *solcs);
int main(void)
{
char *datum = "teststring";
sum(datum);
}
void sum(char *sol)
{
printf("\n value is : %s", sol);
summer_sum(sol);
}
char *summer_sum(char *solcs)
{
int i = 0;
size_t len;
typedef struct {
char *asg[40];
} nlist;
nlist *n1 = malloc(sizeof(*n1));
if (n1 == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
len = strlen(solcs); /* No need to compute len on each iteration */
for (i = 0; i <= 38; i++) { /* you are filling 39 and declared 40 */
n1->asg[i] = calloc(1, len);
/* Always check the result of (m/c/re)alloc */
if (n1->asg[i] == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(n1->asg[i], solcs);
printf("\n %d value is : %s", i, n1->asg[i]);
/* Don't forget to free */
free(n1->asg[i]);
}
free(n1);
return NULL;
}
Before using n1->... You will have allocate memory to n1 as well using calloc()
There are two problems which involves dynamic memory allocation in your code:
n1 is not initialized, you should add a statement like n1 = malloc(sizeof(*n1)); before the for statement in summer_sum()
you did not allocate enough space for each asg[i], you should allocate spaces for these asg[i] by n1->asg[i] = malloc(strlen(**solcs) + 1);
You are using your pointer n1 uninitialized. Your program invokes undefined behavior. In such case you may get either expected or unexpected result.
Second, you are missing a closing brace } in function summer_sum.