in my program, I provide a directory which contains text files. Each of the text files contain a few hundred lines in the following format
Username,Password,BloodType,Domain,Number
I then create a thread for each file in the directory which will merge-sort(by number) these lines into the array char* text_lines[6000];
I can't figure out why I'm getting a segmentation fault because I'm getting different output on every run.
Heres my code:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
void store_line(char* line);
void* my_merge_sort(void* file);
char** text_lines;
int main(int argc, char* argv[])
{
if(argc != 2)
{
fprintf(stderr, "usage: ./coolsort <directory>\n");
}
else
{
text_lines = malloc(6000 * sizeof(char*));
DIR* the_directory;
int filecount = 0;
struct dirent* directory_files[50];
if((the_directory = opendir(argv[1])) != NULL)
{
//make a list of the files in the directory
while((directory_files[filecount++] = readdir(the_directory))) ;
filecount--;
//<<<DEBUGGING INFO>
int i;
fprintf(stderr,"there are %i files in %s:\n", filecount, argv[1]);
for(i = 0; i < filecount; i++)
{
fprintf(stderr, "%s\n",directory_files[i]->d_name);
}
char cwd[512];
chdir(argv[1]);
getcwd(cwd, sizeof(cwd));
fprintf(stderr, "the CWD is: %s\n", cwd);
//<DEBUGGING INFO>>>
//lets start some threads
pthread_t threads[filecount-2];
int x = 0;
for(i = 0; i < (filecount); i++ )
{
if (!strcmp (directory_files[i]->d_name, "."))
continue;
if (!strcmp (directory_files[i]->d_name, ".."))
continue;
pthread_create(&threads[x++], NULL, my_merge_sort, (void*)directory_files[i]->d_name);
}
//do stuff here
//
}
else
{
fprintf(stderr, "Failed to open directory: %s\n", argv[1]);
}
}
}
void* my_merge_sort(void* file)
{
fprintf(stderr, "We got into the function!\n");
FILE* fp = fopen(file, "r");
char* buffer;
char* line;
char delim[2] = "\n";
int numbytes;
//minimize I/O's by reading the entire file into memory;
fseek(fp, 0L, SEEK_END);
numbytes = ftell(fp);
fseek(fp, 0L, SEEK_SET);
buffer = (char*)calloc(numbytes, sizeof(char));
fread(buffer, sizeof(char), numbytes, fp);
fclose(fp);
//now read the buffer by '\n' delimiters
line = strtok(buffer, delim);
fprintf(stderr, "Heres the while loop\n");
while(line != NULL)
{
store_line(line);
line = strtok(buffer, NULL);
}
free(buffer);
}
void store_line(char* line)
{
//extract the ID.no, which is the fifth comma-seperated-token.
char delim[] = ",";
char* buff;
int id;
int i;
strtok(line, delim);
for(i = 0; i < 3; i++)
{
strtok(line, NULL);
}
buff = strtok(line, NULL);
id = atoi(buff);
//copy the line to text_lines[id]
memcpy(text_lines[id], line, strlen(line));
}
edit: I checked to make sure that it would fit into the initial array, and found that the highest ID is only 3000;
You use of strtok() is wrong:
line = strtok(buffer, NULL);
should be
line = strtok(NULL, delim);
Another mistakes should be fixed similarly.
The elements of text_lines are uninitialized:
text_lines = malloc(6000 * sizeof(char*));
this allocated 6000 pointers to char, but none of these pointers are initialized.
Related
I need to read from a file different strings that are comma-separated and storage them into an array.
I have the following code, that I developed reading different questions online.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (){
int N = 300;
int L = 1000;
char Nseq[N][L];
FILE *myfile;
char *token;
const char s[2] = ",";
char line[300];
char* filename = "pathtofile.txt";
int n = 0;
myfile = fopen(filename, "r");
if (myfile == NULL) {printf("could not open file %s", filename); exit(0);}
while (fgets(line, sizeof(line), myfile) != NULL){
token = strtok(line, s);
while (token != NULL){
strcpy(Nseq[n], token);
printf("%s\t%u\n", token, n);
token = strtok(NULL, s);
n++;
}
}
fclose(myfile);
}
my txt file is the following:
1AAAAAAAAAAAAAAAAAAAAAAAAAAAA,2AAAAAAAAAAAAAAAAAAAAAAAAAAAA,3AAAAAAAAAAAAAAAAAAAAAAAAAAAA,4AAAAAAAAAAAAAAAAAAAAAAAAAAAA,5AAAAAAAAAAAAAAAAAAAAAAAAAAAA,6AAAAAAAAAAAAAAAAAAAAAAAAAAAA,7AAAAAAAAAAAAAAAAAAAAAAAAAAAA,8AAAAAAAAAAAAAAAAAAAAAAAAAAAA,9AAAAAAAAAAAAAAAAAAAAAAAAAAAA,10AAAAAAAAAAAAAAAAAAAAAAAAAAAA,11AAAAAAAAAAAAAAAAAAAAAAAAAAAA,12AAAAAAAAAAAAAAAAAAAAAAAAAAAA,13AAAAAAAAAAAAAAAAAAAAAAAAAAAA,14AAAAAAAAAAAAAAAAAAAAAAAAAAAA,15AAAAAAAAAAAAAAAAAAAAAAAAAAAA,16AAAAAAAAAAAAAAAAAAAAAAAAAAAA,17AAAAAAAAAAAAAAAAAAAAAAAAAAAA,18AAAAAAAAAAAAAAAAAAAAAAAAAAAA,19AAAAAAAAAAAAAAAAAAAAAAAAAAAA,20AAAAAAAAAAAAAAAAAAAAAAAAAAAA,21AAAAAAAAAAAAAAAAAAAAAAAAAAAA,22AAAAAAAAAAAAAAAAAAAAAAAAAAAA,23AAAAAAAAAAAAAAAAAAAAAAAAAAAA,24AAAAAAAAAAAAAAAAAAAAAAAAAAAA,25AAAAAAAAAAAAAAAAAAAAAAAAAAAA,26AAAAAAAAAAAAAAAAAAAAAAAAAAAA,27AAAAAAAAAAAAAAAAAAAAAAAAAAAA,28AAAAAAAAAAAAAAAAAAAAAAAAAAAA,29AAAAAAAAAAAAAAAAAAAAAAAAAAAA,30AAAAAAAAAAAAAAAAAAAAAAAAAAAA,
There are 30 strings and no new-line characters.
My issue is that when I run the code, I get the following output:
1AAAAAAAAAAAAAAAAAAAAAAAAAAAA 0
2AAAAAAAAAAAAAAAAAAAAAAAAAAAA 1
3AAAAAAAAAAAAAAAAAAAAAAAAAAAA 2
4AAAAAAAAAAAAAAAAAAAAAAAAAAAA 3
5AAAAAAAAAAAAAAAAAAAAAAAAAAAA 4
6AAAAAAAAAAAAAAAAAAAAAAAAAAAA 5
7AAAAAAAAAAAAAAAAAAAAAAAAAAAA 6
8AAAAAAAAAAAAAAAAAAAAAAAAAAAA 7
9AAAAAAAAAAAAAAAAAAAAAAAAAAAA 8
10AAAAAAAAAAAAAAAAAAAAAAAAAAA 9
A 10
11AAAAAAAAAAAAAAAAAAAAAAAAAAAA 11
12AAAAAAAAAAAAAAAAAAAAAAAAAAAA 12
13AAAAAAAAAAAAAAAAAAAAAAAAAAAA 13
14AAAAAAAAAAAAAAAAAAAAAAAAAAAA 14
15AAAAAAAAAAAAAAAAAAAAAAAAAAAA 15
16AAAAAAAAAAAAAAAAAAAAAAAAAAAA 16
17AAAAAAAAAAAAAAAAAAAAAAAAAAAA 17
18AAAAAAAAAAAAAAAAAAAAAAAAAAAA 18
19AAAAAAAAAAAAAAAAAAAAAAAAAAAA 19
20AAAAAAAAAAAAAAAA 20
AAAAAAAAAAAA 21
21AAAAAAAAAAAAAAAAAAAAAAAAAAAA 22
22AAAAAAAAAAAAAAAAAAAAAAAAAAAA 23
23AAAAAAAAAAAAAAAAAAAAAAAAAAAA 24
24AAAAAAAAAAAAAAAAAAAAAAAAAAAA 25
25AAAAAAAAAAAAAAAAAAAAAAAAAAAA 26
26AAAAAAAAAAAAAAAAAAAAAAAAAAAA 27
27AAAAAAAAAAAAAAAAAAAAAAAAAAAA 28
28AAAAAAAAAAAAAAAAAAAAAAAAAAAA 29
29AAAAAAAAAAAAAAAAAAAAAAAAAAAA 30
30AAAAA 31
AAAAAAAAAAAAAAAAAAAAAAA 32
33
I have tried with different lengths and sooner or later I get these weird splits.
Does someone know why is this happening? thank you!
Your text file is 921 chars in size and is a single line.
Your line buffer is only 300 chars.
So, you're getting truncation.
Also, note that your file has no newline. And, your code didn't handle the case where there is a newline (particularly, if the line ended in ,<newline>).
The simple solution is to increase the size of line so that it is larger than the size of the file (e.g.) char line[10000];
The long term solution is to either read the file char-by-char with (e.g.) fgetc and copy into Nseq[n] and store/print the token after a delimiter.
Or, you can stat the file, and use malloc to allocate a buffer that is the file size.
But, although slightly more advanced, the fastest way [particularly for large files], is to stat the file, mmap it, and then scan the buffer. This will work well on any 64 bit machine, or you could map it in chunks on a 32 bit machine
Here's a version that uses fgetc:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void)
{
int N = 300;
int L = 1000;
char Nseq[N][L];
FILE *myfile;
char *token;
char *filename = "pathtofile.txt";
int chr;
int n = 0;
myfile = fopen(filename, "r");
if (myfile == NULL) {
printf("could not open file %s", filename);
exit(0);
}
token = Nseq[n];
while (1) {
chr = fgetc(myfile);
if (chr == EOF)
break;
switch (chr) {
case ',':
case '\n':
*token = 0;
if (token > Nseq[n]) {
printf("%s\t%u\n", Nseq[n], n);
++n;
}
token = Nseq[n];
break;
default:
*token++ = chr;
break;
}
}
fclose(myfile);
return 0;
}
Here's a version that uses malloc:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
int
main(void)
{
int N = 300;
int L = 1000;
char Nseq[N][L];
FILE *myfile;
char *token;
const char s[2] = ",";
char *line;
int len;
char *filename = "pathtofile.txt";
int err;
struct stat st;
int n = 0;
err = stat(filename,&st);
if (err < 0) {
printf("could not stat file %s", filename);
exit(1);
}
len = st.st_size + 1;
line = malloc(len);
myfile = fopen(filename, "r");
if (myfile == NULL) {
printf("could not open file %s", filename);
exit(1);
}
while (fgets(line, len, myfile) != NULL) {
token = strtok(line, s);
while (token != NULL) {
strcpy(Nseq[n], token);
printf("%s\t%u\n", token, n);
token = strtok(NULL, s);
n++;
}
}
fclose(myfile);
return 0;
}
Here's a version that uses mmap:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
int
main(void)
{
int N = 300;
int L = 1000;
char Nseq[N][L];
char *token;
char *line;
char *cur;
char *end;
char *filename = "pathtofile.txt";
int fd;
int chr;
int n = 0;
int err;
struct stat st;
size_t len;
fd = open(filename,O_RDONLY);
if (fd < 0) {
printf("could not open file %s", filename);
exit(1);
}
err = fstat(fd,&st);
if (err < 0) {
printf("could not stat file %s", filename);
exit(1);
}
len = st.st_size;
line = mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0);
if (line == MAP_FAILED) {
printf("could not mmap file %s", filename);
exit(1);
}
cur = line;
end = &line[len];
token = Nseq[n];
for (cur = line; cur < end; ++cur) {
chr = *cur;
switch (chr) {
case ',':
case '\n':
*token = 0;
if (token > Nseq[n]) {
printf("%s\t%u\n", Nseq[n], n);
++n;
}
token = Nseq[n];
break;
default:
*token++ = chr;
break;
}
}
munmap(line,len);
close(fd);
return 0;
}
I was just creating simple implementation where I read input.txt file which has one line of code containing two numbers separated by space (e.g. 4 4).
I was trying to separate them by delimiting with space first.
And I was trying to use the first value as a size of char array.
However it keeps causing segmentation fault but I have no idea.
int main(int argc, char **argv){
int number;
int i = 0;
char *token;
char buf[100];
int tempNum[2];
// Open file
FILE * fPointer;
fPointer = fopen("input.txt", "r");
// Read first line
fgets(buf, 1024, fPointer);
token = strtok(buf, " ");
number = atoi(token);
char charArray[number];
while(token != NULL){
tempNum[i] = atoi(token);
token = strtok(NULL, "\n");
printf("%d\n", tempNum[i]);
i++;
}
If I comment out "char charArray[number]" it does not cause segmentation fault. If I comment out only the while loop, it does not cause segmentation fault. But I cannot figure out why it is causing the segmentation in the first place. Please help.
Thank you in advance.
Something like this?
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#define BUF_SIZE 1024
#define MAX_INPUT 2
int main(int argc, char **argv) {
char *token = NULL;
char *next_token = NULL;
char buf[BUF_SIZE];
long tempNum[MAX_INPUT] = { 0 };
const char *delim = " ";
char * end = NULL;
// Init vars
memset(buf, 0, BUF_SIZE);
// Open file
FILE * fPointer = fopen("input.txt", "r");
if (fPointer == NULL) {
return 1;
}
// Read first line
if (fgets(buf, BUF_SIZE, fPointer) == NULL) {
fclose(fPointer);
return 2;
}
// Parse line
token = strtok_s(buf, delim, &next_token);
for (int i = 0;((i < MAX_INPUT) && (token != NULL)); i++){
tempNum[i] = strtol(token, &end, 10);
if (*end != NULL){
printf("error in %s\n", token);
} else {
printf("%d\n", tempNum[i]);
}
token = strtok_s(NULL, delim, &next_token);
}
fclose(fPointer);
return 0;
}
In the below code, the file test.txt has the following data :
192.168.1.1-90
192.168.2.2-80
The output of this is not as expected.
I expect the output to be
192.168.1.1
90
192.168.2.2
80
Any help would be much appreciated.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
char *result[10][4];
int i=0;
const char s[2] = "-";
char *value,str[128];
fp = fopen("test.txt", "r");
if (fp == NULL)
printf("File doesn't exist\n");
else{
while(!feof(fp)){
if(fgets(str,sizeof(str),fp)){
/* get the first value */
value = strtok(str, s);
result[i][0]=value;
printf("IP : %s\n",result[i][0]); //to be removed after testing
/* get second value */
value = strtok(NULL, s);
result[i][1]=value;
printf("PORT : %s\n",result[i][1]); //to be removed after testing
i++;
}}
for (int k=0;k<2;k++){
for (int j=0;j<2;j++){
printf("\n%s\n",result[k][j]);
}
}
}
return(0);
}
You can try this solution. It uses dynamic memory instead, but does what your after.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFSIZE 128
void exit_if_null(void *ptr, const char *msg);
int
main(int argc, char const *argv[]) {
FILE *filename;
char buffer[BUFFSIZE];
char *sequence;
char **ipinfo;
int str_size = 10, str_count = 0, i;
filename = fopen("ips.txt", "r");
if (filename == NULL) {
fprintf(stderr, "%s\n", "Error Reading File!");
exit(EXIT_FAILURE);
}
ipinfo = malloc(str_size * sizeof(*ipinfo));
exit_if_null(ipinfo, "Initial Allocation");
while (fgets(buffer, BUFFSIZE, filename) != NULL) {
sequence = strtok(buffer, "-\n");
while (sequence != NULL) {
if (str_size == str_count) {
str_size *= 2;
ipinfo = realloc(ipinfo, str_size * sizeof(*ipinfo));
exit_if_null(ipinfo, "Reallocation");
}
ipinfo[str_count] = malloc(strlen(sequence)+1);
exit_if_null(ipinfo[str_count], "Initial Allocation");
strcpy(ipinfo[str_count], sequence);
str_count++;
sequence = strtok(NULL, "-\n");
}
}
for (i = 0; i < str_count; i++) {
printf("%s\n", ipinfo[i]);
free(ipinfo[i]);
ipinfo[i] = NULL;
}
free(ipinfo);
ipinfo = NULL;
fclose(filename);
return 0;
}
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
The key thing to understand is that char *strtok(char *str, const char *delim) internally modifies the string pointed to by str and uses that to store the result. So the returned pointer actually points to somewhere in str.
In your code, the content of str is refreshed each time when you parse a new line in the file, but the address remains the same. So after your while loop, the content of str is the last line of the file, somehow modified by strtok. At this time, result[0][0] and result[1][0] both points to the same address, which equals the beginning of str. So you print the same thing twice in the end.
This is further illustrated in the comments added to your code.
int main()
{
FILE *fp;
char *result[10][4];
int i=0;
const char s[2] = "-";
char *value,str[128];
fp = fopen("test.txt", "r");
if (fp == NULL)
printf("File doesn't exist\n");
else{
while(!feof(fp)){
if(fgets(str,sizeof(str),fp)){
/* get the first value */
value = strtok(str, s);
// ADDED: value now points to somewhere in str
result[i][0]=value;
// ADDED: result[i][0] points to the same address for i = 0 and 1
printf("IP : %s\n",result[i][0]); //to be removed after testing
/* get second value */
value = strtok(NULL, s);
// ADDED: value now points to somewhere in str
result[i][1]=value;
// ADDED: result[i][1] points to the same address for i = 0 and 1
printf("PORT : %s\n",result[i][1]); //to be removed after testing
i++;
}}
// ADDED: now result[0][0]==result[1][0], result[0][1]==result[1][1], you can test that
for (int k=0;k<2;k++){
for (int j=0;j<2;j++){
printf("\n%s\n",result[k][j]);
}
}
}
return(0);
}
To get the expected output, you should copy the string pointed by the pointer returned by strtok to somewhere else each time, rather than just copy the pointer itself.
int main()
{
//FILE *out = fopen("keimeno.txt", "w+");
FILE *in = fopen("keimeno.txt", "r");
int fullbufflen=0 , i;
char buffer[100];
fgets(buffer, 100, in);
int bufflen = strlen(buffer);
char *text;
text =calloc(bufflen,sizeof(char));
char *strcat(text, buffer);
// printf("line of \"keimeno.txt\": %s", buffer);
// printf("size of line \"keimeno.txt\": %i\n\n", bufflen);
fullbufflen = bufflen;
while(fgets(buffer, 100, in)!=NULL)
{
// printf("line of \"keimeno.txt\": %s", buffer);
// printf("size of line \"keimeno.txt\": %i\n\n", bufflen);
text =realloc(text,bufflen*sizeof(char));
char *strcat(text, buffer);
fullbufflen = bufflen + fullbufflen ;
}
for (i = 0;i<fullbufflen;i++)
{
printf("%c\n",text[i]);
}
}
I am trying to copy the full text file (keimeno.txt) into a dynamic memory array, with a buffer of 100 character at most everytime. To test it at the end i tried to prinf the results. And i just cant get it to work. Dont know if there is a problem on the printf at the end, or the whole program is just wrong.
Also the dynamic array is supposed to have 0 size at the beggining, so if someone could tell me how to do that too, it would be welcome.
Thanks in advance.
There are a few issues:
char *strcat(text, buffer);
This is not how you call a function. This is a function declaration, and an incorrect one at that since it doesn't define the types of the arguments.
To call strcat, just do this:
strcat(text, buffer);
Next, you're not allocating enough space for your buffers:
text =calloc(bufflen,sizeof(char));
You need to add space for the null bytes that terminates the string:
text =calloc(bufflen + 1,sizeof(char));
Similarly here:
text =realloc(text,bufflen*sizeof(char));
This only reallocates a total of bufflen bytes. It does not add bufflen bytes to what was already allocated, and bufflen is unchanged from when it was first set outside of the while loop. Do this instead:
bufflen = strlen(buffer);
text =realloc(text,bufflen+fullbufflen+1);
This gives you enough space for the current length, the additional buffer, and the null byte.
Finally, make sure you fclose(in) and free(text) at the end to clean up your resources, and be sure to check the return value of fopen to ensure that the file opened successfully, and realloc/calloc to ensure that your allocations worked.
After the above changes, you code should look like this:
int main(void)
{
//FILE *out = fopen("keimeno.txt", "w+");
FILE *in = fopen("keimeno.txt", "r");
if (in == NULL) {
perror("open failed");
exit(1);
}
int fullbufflen=0 , i;
char buffer[100];
fgets(buffer, 100, in);
int bufflen = strlen(buffer);
char *text;
text =calloc(bufflen+1,sizeof(char));
if (text == NULL) {
perror("calloc failed");
exit(1);
}
strcat(text, buffer);
// printf("line of \"keimeno.txt\": %s", buffer);
// printf("size of line \"keimeno.txt\": %i\n\n", bufflen);
fullbufflen = bufflen;
while(fgets(buffer, 100, in)!=NULL)
{
// printf("line of \"keimeno.txt\": %s", buffer);
// printf("size of line \"keimeno.txt\": %i\n\n", bufflen);
bufflen = strlen(buffer);
text =realloc(text,bufflen+fullbufflen+1);
if (text == NULL) {
perror("realloc failed");
exit(1);
}
strcat(text, buffer);
fullbufflen = bufflen + fullbufflen ;
}
fclose(in);
for (i = 0;i<fullbufflen;i++)
{
printf("%c\n",text[i]);
}
free(text);
}
Here is one possible solution:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#define ERR (-1)
#define GROW 100
static void die ( const char * msg ) { perror(msg); exit(1); }
int main ( void ) {
char * filename = "in.txt";
size_t buffSize = 0;
size_t buffUsed = 0;
ssize_t bytesRead = 0;
char * buffer = NULL;
char * tmp;
int fd;
fd = open(filename, O_RDONLY, 0);
if (fd == ERR) die("open");
do {
buffUsed += (size_t)bytesRead;
if (buffUsed == buffSize) {
tmp = realloc(buffer, buffSize += GROW);
if (tmp == NULL) die("realloc");
buffer = tmp;
}
bytesRead = read(fd, buffer + buffUsed, buffSize - buffUsed);
if (bytesRead == ERR) die("read");
} while (bytesRead > 0);
if (write(STDOUT_FILENO, buffer, buffUsed) == ERR) die("write");
free(buffer);
if (close(fd) == ERR) die("close");
return 0;
}
Like the original, the input filename is hard-coded which sub-optimal...
My code is not putting the text file data into line on the second pass of the while loop, and any subsequent pass. I'm sure it's a silly error but I cannot find it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *fr;
char *line,*word,*vali;
ssize_t read;
int i=0,sum=0,len =0,flag=0;
const char delim[2]=" ";
int main(int argc, char* argv[])
{
line = (char *)malloc(sizeof(&len));
word = (char *)malloc(sizeof(&len));
vali = (char *)malloc(sizeof(&len));
fr = fopen(argv[1], "r");
if(fr==NULL)
{
exit(EXIT_FAILURE);
}
while ((read = getline(&line, &len, fr)) != -1)
{
printf("line is %s\n", line );
fscanf(fr,"%s%*[^\n]",word);
printf("%s ", word);
vali=strtok(line, delim);
while(vali != NULL)
{
sum=sum+atoi(vali);
vali = strtok(NULL, delim);
}
printf("%d\n", sum);
sum=0;
vali=" ";
len = strlen(line);
}
fclose(fr);
if (line)
free(line);
return 0;
}
If len is some integral type containing the desired length of the first line, then:
&len
Has type pointer-to-integer, and
sizeof(&len)
Returns the size of a pointer (8 bytes on most 64 bit systems) and
malloc(sizeof(&len))
Allocates only 8 bytes of memory (or whatever pointer size is on your system).
This is probably at least part of the issue.