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.
Related
I have a piece of code that looks like this
#include <stdio.h>
int main()
{
int i;
int number_of_chunks = 12;
char *final_string = NULL;
for(i = 0; i < number_of_chunks; i++)
{
char *chunk = some_hash_table.pop(i);
asprintf(&final_string, "%s%s", (final_string==NULL?"":final_string), chunk);
}
free(final_string);
return 0;
}
Here I am concatinating string chunks dynamically, meaning I don't know the size of each chunk in advance. For this I am using asprintf. The code works fine, however rise some serious memory issue. My doubt is asprintf allocates memory in each iteration and the code loses pointer in each iteration. If there is any other way I can concate string inside loop please guide me
To put your question in the simplest possible way, what you are essentially trying to do with the above code is
1. Allocate memory to a pointer continuously(in your case 12 times in the for loop) and
2. free it at the end only once, which is causing memory leak.
Like in the below code
#include <stdio.h>
int main()
{
int i;
int number_of_chunks = 12;
char *final_string = NULL;
for(i = 0; i < number_of_chunks; i++)
{
/*For example: similar to what asprintf does, allocate memory to the pointer*/
final_string = malloc(1);
}
free(final_string);
return 0;
}
From the above example it is easily visible that you have allocated the memory 12 times but freed only once.
code snippet:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i;
int number_of_chunks = 12;
char *final_string = NULL;
char *tmp = NULL;
for(i = 0; i < number_of_chunks; i++)
{
char *chunk = some_hash_table.pop(i);
asprintf(&final_string, "%s%s", (tmp==NULL?"":tmp), chunk);
if (tmp)
free(tmp);
tmp = final_string;
}
printf("%s\n", final_string);
free(final_string);
return 0;
}
Others have already pointed out that you lose the reference to all but the last allocation and that having the same string that is written to as printf argument is probably undefined behaviour, even more so as re-allocations might occur and invalidate the format argument.
You don't use asprintf's formatting capabilities, you use it only to concatenate strings, so you might want to take another approach. You could either collect the strings in an array, determine the needed length, allocate as appropriate and fill the allocated buffer with memcpy.
Or you could write a self-allocating string buffer similar to C++'s std::stringstream, for example:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct append_t {
char *str; /* string */
size_t len; /* length of string */
size_t size; /* allocated size */
};
void append(struct append_t *app, const char *str)
{
size_t len = strlen(str);
while (app->len + len + 1 >= app->size) {
app->size = app->size ? app->size * 2 : 0x100;
app->str = realloc(app->str, app->size);
/* error handling on NULL re-allocation */
}
strcpy(app->str + app->len, str);
app->len += len;
}
int main(int argc, char **argv)
{
struct append_t app = {NULL};
for (int i = 1; i < argc; i++) {
append(&app, argv[i]);
}
if (app.str) puts(app.str);
free(app.str);
return 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void sortString(const char* input, char* output);
int cmpstr(void const *a,void const *b);
int readAllWords(FILE* f, char*** res, int * num_read);
int main (int argc, char ** argv)
{
char **wordList;
FILE* fid;
int numWords;
fid = fopen(argv[1],"r");
readAllWords(fid, &wordList,&numWords);
}
int readAllWords(FILE* f, char*** res, int * num_read)
{
char buffer[128];
*num_read = 0;
int size;
while(fgets(buffer,128,f))
{
*num_read = *num_read +1;
size = strlen(buffer);
res = (char***)malloc(sizeof(char**));
*res = (char **)realloc(*res,sizeof(char*)*(*num_read));
(*res)[(*num_read)-1] = (char *)realloc((*res)[(*num_read)-1],sizeof(char)*size);
strcpy((*res)[(*num_read)-1],buffer);
printf("%s\n",(*res)[(*num_read)-1]);
}
printf("%s\n",(*res)[0]);
}
The values are storing and it prints out inside the while loop. But after the while loop, it cannot print out the strings.
The File is given in the main function. Do not understand why realloc is causing the loss of data?
One problem is that the code doesn't initialize res in main(), so you attempt to realloc() an indeterminate value. Either NULL or a value previously returned by malloc() or realloc() (or calloc()) would be OK, but since you pass an indeterminate value, you are invoking undefined behaviour, and a crash is a valid response to doing that.
However, there's a lot of other code in the function that should be reviewed as well.
This code works, and gets a clean bill of health from valgrind.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void readAllLines(FILE *f, char ***res, int *num_read);
int main(int argc, char **argv)
{
char **wordList = 0;
FILE *fid;
int numLines = 0;
if (argc > 1 && (fid = fopen(argv[1], "r")) != 0)
{
readAllLines(fid, &wordList, &numLines);
fclose(fid);
for (int i = 0; i < numLines; i++)
printf("%d: %s", i, wordList[i]);
for (int i = 0; i < numLines; i++)
free(wordList[i]);
free(wordList);
}
return 0;
}
void readAllLines(FILE *f, char ***res, int *num_read)
{
char buffer[128];
int size;
while (fgets(buffer, sizeof(buffer), f))
{
*num_read = *num_read + 1;
size = strlen(buffer) + 1;
char **space = (char **)realloc(*res, sizeof(char *) * (*num_read));
if (space == 0)
return;
*res = space;
(*res)[*num_read - 1] = (char *)malloc(sizeof(char) * size);
if ((*res)[*num_read - 1] == 0)
return;
strcpy((*res)[*num_read - 1], buffer);
printf("%s\n", (*res)[*num_read - 1]);
}
printf("%s\n", (*res)[0]);
}
Possible reason for a segmentation fault:
res = (char***)malloc(sizeof(char**));
*res = (char **)realloc(*res,sizeof(char*)*(*num_read));
In the second line you try to reallocate whatever *res is pointing to. However since you did not initialize *res this could be anything. This will work only if *res == NULL. I guess it should be malloc, not realloc.
Other problems:
You allocate everything new in each loop iteration. This is a huge memory leak.
You already pass a valid memory address pointing to an char** by res, you shouldn't allocate for it again. It is an out parameter. (Remove the malloc call)
You need an initial malloc for *res before the loop (Or set *res = NULL).
The second realloc for *res[...] should be a malloc, because you never actually reallocate here. Also instead of allocating size bytes, you should allocate size+1 bytes for the terminating \0.
Your function has no return statement although it is non-void.
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.
My program compiles but I am not working with pointers and realloc correctly. I have tried looking at other examples but I can't seem to translate it to my own program. The point of the program is to read in words from a file and increment the count if they appear more than once. Once the array of structs goes over my base (5), I want to realloc space, copy the array over and then add the next word.
Any help would be greatly appreciated!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BASE 5
#define MAX 50
typedef char *string;
struct wordCount
{
string word;
unsigned int count;
};
int main (void)
{
unsigned int i;
unsigned int incremented;
unsigned int j;
char temp [40];
struct wordCount wordArray[BASE];
struct wordCount *holder;
FILE *infile;
j = 0;
infile = fopen("input.txt","r");
while (fscanf(infile, "%s", temp) == 1) {
incremented = 0;
for (i = 0; i < j; i++){
if(strcmp(temp,wordArray[i].word) == 0){
wordArray[i].count++;
incremented++;
}
}
if (incremented == 0){
if (j<BASE){
wordArray[j].word = (char *)malloc((strlen(temp)+1) *
sizeof(char));
strcpy(wordArray[j].word,temp);
wordArray[j].count = 1;
j++;
} else {
holder = realloc(wordArray, sizeof(wordArray) +1);
*wordArray = *holder;
wordArray[j].word = (char *)malloc((strlen(temp)+1) * sizeof(char));
strcpy(wordArray[j].word,temp);
wordArray[j].count = 1;
j++;
}
}
}
fclose(infile);
/* bring in next file*/
/*delete du plicates */
/*sort*/
for (i = 0; i < j; i++) {
printf("%s ", wordArray[i].word);
printf("%d\n", wordArray[i].count);
}
/* and when done:*/
for(i = 0; i < j; i++){
free(wordArray[i].word);
}
return 0;
}
Here's the most obvious place you're going wrong:
holder = realloc(wordArray, sizeof(wordArray) +1);
Note this line from the man page of realloc():
void *realloc(void *ptr, size_t size);
...
Unless ptr is NULL, it must have been returned by an earlier call to malloc(), calloc() or realloc().
Your wordArray is a statically allocated array, it was not dynamically allocated via malloc() or friends.
I'm new at programming. I have:
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // With luck, this declares strdup()
enum { ROWS = 50 };
static char *funkc(FILE *fp,char file[50])
{
int q,row;
char charbuffer[2],ch,*map[ROWS];
ch=getc(fp);
q=1;
while (ch!=EOF){
ch=getc(fp);
q++;
}
for (row = 0; row <=q; row++){
map[row] = " ";
}
fp = fopen(file, "r");
for (row = 0; row <= q; row++) {
if (fgets(charbuffer, 2, fp))
map[row] = strdup(charbuffer);
}
for (row = 0; row <= q; row++) {
printf("%s", map[row]);
}
return map[3];
}
int main(void)
{
char *map2[ROWS];
FILE *fp;
char file[50]; // Unused variable *map[ROWS];
printf("file name \n");
scanf("%s",file); // Removed ampersand from file
if ((fp=fopen(file,"r"))==NULL)
{
printf("Error \n");
exit(1);
}
map2[0]=funkc(fp,file);
printf("%s",map2[0]); // Add missing semicolon
return 0;
}
With that I can return only single char but I need to return full char array (map[ROWS]); how can I do it?
I think there are some problems in your code.
First, how can you use this piece of code?
scanf("%s", &file);
I think what you need to do is this one:
scanf("%s", file);
Because the array name file is a pointer itself, you don't need to use &.
Second, you can get an array of chars by return map[0], because it is a char * type, namely a string in C. Think about it.
If you pass an array to a function, any changes made to that array in the function will be accessible by your main function. This means that you don't have to return the array, just modify your array in funkc and main will see the new array.
In C, most variables are passed by value. If a variable's value is modified in a function, the new value will not be accessible elsewhere in the program. However, arrays are passed by reference, so funck has access to the array's memory. See here for more information:
http://staff.um.edu.mt/csta1/courses/lectures/csa2060/c6.html
Not reading your code thoroughly,
But your main problem is quite clear,
you need to study more about: pass by address, array, pointer.
Below are my very simple code to pass array for function and return to main.
You either pass by adress(array itself is), or pass a malloced pointer(remeber to free).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int test(char *map)
{
strcpy(map, "hello, world");
return 0;
}
int main(int argc, char **argv)
{
char map[20];
//char *map = malloc(sizeof(char) * 20);
test(map);
printf("%s\n", map);
//free(map);
return 0;
}
Two things you need to do, besides fixing other errors in the code:
You are expecting to get an array of strings, which would be char** type.
You also need to allocate memory for an array, as returning automatic variable reference is not a good idea. Also you need to allocate memory for every entry in the array, as mixing static string references and allocated memory is not a good idea either.
include ...
enum { ROWS = 50 };
static char **funkc(FILE *fp)
{
long fileSize = 0;
int row;
char **map = NULL;
map = (char**)calloc(ROWS, sizeof(char*));
fseek(fp, SEEK_END, 0);
fileSize = ftell(fp);
fseek(fp, SEEK_SET, 0);
for (row = 0; row < fileSize && row < ROWS; row++)
{
char buffer[2];
buffer[0] = fgetc(fp);
buffer[1] = 0;
map[row] = strdup(buffer);
}
for (;row < ROWS; row++)
{
map[row] = strdup(" ");
}
return map;
}
int main(int argc, const char *argv[])
{
char **map;
FILE *fp;
char fname[50];
int row;
printf("file name \n");
scanf("%s", fname);
fp = fopen(fname, "r");
map = funkc(fp);
fclose(fp);
for (row = 0; row < ROWS; ++row)
{
printf("ROW[%d]: %s\n", row, map[row]);
}
for (row = 0; row < ROWS; ++row)
{
free(map[row]);
}
free(map);
return 0;
}