I'm coding a program to crack the CRC16. I've been having some problems with outputting the file and keep the calculated CRC16(have no idea why it changes when I write it to a file). So what I'm doing here is read the input file, writing it to a output file with some gibberish and then I read the output file again and calculate it's CRC16. If it matches with the desired CRC16, then it is done. However after a bunch of executions the fgets() method crashes with a Seg fault.
Anyone could help me? Please ignore the performance issues, this is a test.
int main(int argc, char* argv[]){
char outfile[strlen(argv[1])];
strcpy(outfile,argv[1]);
strcat(outfile,".crack");
char crc16[5];
strcpy(crc16,argv[2]);
char newcrc16[5];
char gebrish[80];
char cat[2];
int full = 1;
int p = 0;
int i,j,k;
for(i=32; i< 128;i++)
for(j=32; j< 128; j++)
for(k=32; k < 128; k++){
gebrish[0] =i;
gebrish[1] =j;
gebrish[2] =k;
gebrish[3] = '\n';
gebrish[4] ='\0';
boost::crc_16_type result;
FILE* file;
FILE* out;
char line[100];
printf("read out\n");
out = fopen(outfile,"w");
printf("read file\n");
file = fopen(argv[1],"r");
printf("wrt\n");
while(fgets(line,80,file) != NULL){
fputs(line,out);
}
fputs(gebrish,out);
fclose(file);
fclose(out);
printf("read gain\n");
out = fopen(outfile,"r");
while(fgets(line,80,out) != NULL){
result.process_bytes(line,strlen(line));
printf("%s",line);
}
int crc = result.checksum();
sprintf(newcrc16,"%x",crc);
printf("%s",newcrc16);
if(strcmp(crc16,newcrc16) == 0){
printf("%s",gebrish);
return 0;
}
}
return 0;
}
This causes a buffer overrun:
char outfile[strlen(argv[1])];
strcpy(outfile,argv[1]);
strcat(outfile,".crack");
as there is not enough space in outfile for terminating null character and ".crack". It will be overwriting memory it is not supposed to and may be the cause of the segmentation fault.
Change to:
char outfile[strlen(argv[1]) + 1 + 6];
strcpy(outfile,argv[1]);
strcat(outfile,".crack");
Before accessing argv elements ensure they have been provided by checking argc:
if (argc > 2)
{
/* Safe to use argv[1] and argv[2]. */
}
Check return values from fopen() also.
The error is most likely due to not checking the return value from open, and then calling fgets on a bad file. Returns from system calls should always be checked if subsequent operations depend on them. Even close can fail.
The problem is that I tried to Read and Write from the same file in different moments without calling fclose() after the use. This way after some execution of the loop it crashes with a STATUS_VIOLATION. I have no idea why it didn't crash right away, but all I did was add a flcose() after reading the file for the CRC16 calculation.
Related
We were supposed to extract strings from a provided file, the output matches the expect, but it reports segmentation fault in the end and I don't know why.
#include<stdio.h>
#include<string.h>
int main(int argc, char *argv[]){
char str[100];
char f;
int len = 0;
FILE *file;
file = fopen(argv[1],"r");
//read only here, so use "r"
if(file==NULL){
printf("The file doesn't exist.\n");
return 1;
}
while(feof(file)==0){
//if feof returns 0 it means it havent reaches the end yet
fread(&f,sizeof(f),1,file);//read in the file
//printabel character between 32 and 126
if(f>=32&&f<=126){
str[len] = f;
len++;
continue;//keep doing it(for ->while)
}
if(strlen(str)>3){
//a string is a run of at least 4
printf("The output is:%s\n",str);
len=0;//reset
memset(str, 0, sizeof(str));
//reset the str so it wont get too big(overflow)
}
}
//close the file and return
fclose(file);
return 0;
}
This is not true
while(feof(file)==0){
//if feof returns 0 it means it havent reaches the end yet
And a very common mistake.
This returns 0 if you have Not read past the end of file. Its s subtle but important detail. Your last read may have read up-to the end of file but not past it. This means there is actually no data left to read but feof() will still return 0.
This is why you must test the result of the read operation.
fread(&f,sizeof(f),1,file);
If this returns zero then you failed to read anything.
Which is why you should structure your loop to test the result of the read (not feof()).
while (fread(&f,sizeof(f),1,file) == 1)
{
// You have successfully read an object from the stream
}
Your code has some fundamental errors:
See Why is while ( !feof (file) ) always wrong?
You don't check if fread returns 0, meaning that no more character could be
read, yet you continue with your algorithm
str is not '\0'-terminated, the strlen(str)>3 yields undefined
behaviour in the first iteration and will likely be evaluated as true right in the first iteration.
Then the printf would also yield undefined behaviour for the same reason.
Don't use the ASCII code directly, it's hard to read, you have to look up in
the ASCII table to see what 32 is and what 126. Better use the character
constants
if(f>= ' ' && f <= '~'){
...
}
This is easier to read and you get the intention of the code immediately.
So the program can be rewritten like this:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
char str[100];
char f;
int len = 0;
FILE *file;
file = fopen(argv[1],"r");
//read only here, so use "r"
if(file==NULL){
printf("The file doesn't exist.\n");
return 1;
}
memset(str, 0, sizeof str);
while(fread(&f, sizeof f, 1, file) == 1)
{
if(f >= ' ' && f <= '~')
{
str[len++] = f;
continue;
}
if(strlen(str) > 3) // or if(len > 3)
{
printf("The output is: %s\n", str);
len = 0;
memset(str, 0, sizeof str);
}
}
fclose(file);
return 0;
}
The code is supposed to read a user-inputted text file name, copy every character into a multidimensional array, then display it with standard output. It compiles, but produces unintelligible text. Am I missing something?
for (i = 0; i < BIGGEST; i++) {
for (j = 0; j < BIGGESTL; j++) {
if (fgetc(array, fp) ) != EOF)
array[i][j] = c;
else array[i][j] = '\0'
}
fclose(fp);
return 0;
}
You stop filling the array when you encounter EOF, but you print the full array out no matter what.
If the data read from the file is smaller than the input array, you will read that data in and then print that data out, plus whatever random characters were in the memory locations that you do not overwrite with data from the file.
Since the requirement seems to be to print text data, you could insert a special marker in the array (e.g. '\0') to indicate the position where you encountered EOF, and stop displaying data when you reach that marker.
You had better read each line from file
For example:
int i = 0;
while(fgets(text[i],1000,fp))
{
i++;
}
Though the question is edited and only part of the code is left in question. I am posting more than what is required for the question at the moment.
Reason being, there can be numberous improvements to originally posted full code.
In main() function:
You need to check for the argc value to be equal to 2 for your purpose and only then read in value of argv[1] . Else if program executed without the command-line-argument which is file_name in this case, invalid memory read occurs, resulting in segmentation fault if you read in argv[1].
In read_file_and_show_the contents() function:
Stop reading file if end of file is reached or maximum characters is read and store in the character array.
Below Program will help you visualize:
#include <stdio.h>
/*Max number of characters to be read/write from file*/
#define MAX_CHAR_FOR_FILE_OPERATION 1000000
int read_and_show_the_file(char *filename)
{
FILE *fp;
char text[MAX_CHAR_FOR_FILE_OPERATION];
int i;
fp = fopen(filename, "r");
if(fp == NULL)
{
printf("File Pointer is invalid\n");
return -1;
}
//Ensure array write starts from beginning
i = 0;
//Read over file contents until either EOF is reached or maximum characters is read and store in character array
while( (fgets(&text[i++],sizeof(char)+1,fp) != NULL) && (i<MAX_CHAR_FOR_FILE_OPERATION) ) ;
//Ensure array read starts from beginning
i = 0;
while((text[i] != '\0') && (i<MAX_CHAR_FOR_FILE_OPERATION) )
{
printf("%c",text[i++]);
}
fclose(fp);
return 0;
}
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("Execute the program along with file name to be read and printed. \n\
\rFormat : \"%s <file-name>\"\n",argv[0]);
return -1;
}
char *filename = argv[1];
if( (read_and_show_the_file(filename)) == 0)
{
printf("File Read and Print to stdout is successful\n");
}
return 0;
}
I posted a problem yesterday regarding a certain segment of my code. The aim was to basically scan in data values from a .dat file into an array, print the values whilst also counting how many values were in the file.
Sounds pretty simple, but my program only seemed to print a certain number of the values. More specifically, of a data file containing over 300000 values, it would only print the last 20000 and nothing else.
So I left it, finished the rest of my code and now it's the last part I have to sort. I've made a few changes and tried actually printing an output .dat file now so I can see what I'm getting. The code is below by the way.
Initally I assumed perhaps it was something related to the memory allocation of my array (was getting a segmentation error? when putting the whole code together) so I created an external function that counted the number of values instead (that works).
My only problem now is that it still only chooses to print 20000 values and then the rest are 0s. I was thinking perhaps it had something to do with the type but they all contain 7 dps in scientific notation. Here's a sample of some of the values:
8.4730000e+01 1.0024256e+01
8.4740000e+01 8.2065599e+00
8.4750000e+01 8.3354644e+00
8.4760000e+01 8.3379525e+00
8.4770000e+01 9.8741315e+00
8.4780000e+01 9.0966478e+00
8.4790000e+01 9.4760274e+00
8.4800000e+01 7.1199807e+00
8.4810000e+01 7.1990172e+00
Anyone see where I'm going wrong? I'm sorry for the long question, it's just been bugging me for the last day or so and no matter what I change nothing seems to help. Any kind of input would be greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
int count(int);
const char df[]="data_file.dat";
const char of[]="output_file.dat";
int main(int argc, char *argv[])
{
FILE *input, *output;
int i, N;
float *array;
N = count(i);
input = fopen(df, "r");
output = fopen(of, "w");
array = (float*)malloc(N*sizeof(float));
if((input != (FILE*) NULL) && (output != (FILE*) NULL))
{
for(i = 0; i < N; i++)
{
fscanf(input, "%e", &array[i]);
fprintf(output, "%d %e\n", i, array[i]);
}
fclose(input);
fclose(output);
}
else
printf("Input file could not be opened\n");
return(0);
}
int count(int i)
{
FILE *input;
input = fopen(df, "r");
int N = 0;
while (1)
{
i = fgetc(input);
if (i == EOF)
break;
++N;
}
fclose(input);
return(N);
}
Your biggest problem is that count() doesn't count float values; it counts how many characters are in the file. Then you try to loop and call fscanf() more times than there are values in the file. The first times, fscanf() finds a float value and scans it; but once the loop reaches the end of file, fscanf() will be returning an EOF status. It seems possible that fscanf() will set the float value to 0.0 when it returns EOF.
I suggest you rewrite so that you don't try to pre-count the float values. Write a loop that just repeatedly calls fscanf() until it returns an EOF result, then break out of the loop and close the files.
P.S. If you are going to write a function like count(), you should pass in the filename as an argument instead of hard-coding it. And your version of count() takes an integer argument but just ignores the value; instead, just declare a temp variable inside of count().
EDIT: Okay, here is a complete working program to solve this problem.
#include <stdio.h>
int
main(int argc, char **argv)
{
FILE *in_file, *out_file;
unsigned int i;
if (argc != 3)
{
fprintf(stderr, "Usage: this_program_name <input_file> <output_file>\n");
return 1; // error exit with status 1
}
in_file = fopen(argv[1], "r");
if (!in_file)
{
fprintf(stderr, "unable to open input file '%s'\n", argv[1]);
return 1; // error exit with status 1
}
out_file = fopen(argv[2], "w");
if (!out_file)
{
fprintf(stderr, "unable to open output file '%s'\n", argv[2]);
return 1; // error exit with status 1
}
for (i = 0; ; ++i)
{
int result;
float x;
result = fscanf(in_file, "%e", &x);
if (1 != result)
break;
fprintf(out_file, "%d %e\n", i, x);
}
return 0; // successful exit
}
Note that this version doesn't need to allocate a large array; it just needs a single temporary float variable. Maybe your program will need to store all the float values. In that case, write a count() function that uses a loop similar to the above loop, using fscanf() to count float values.
Also note that this program checks for errors after calling fopen() and fscanf().
You are allocating far more floats in memory (N) than you need because your N is the number of characters in the file, not the number of values in it.
Also, how did you determine that there are 300000 values in the file?
I have difficulty using malloc and fscanf.
I just want to read a file and print out the result using
I got a segmentation fault error when I executed this code.
I am not sure what I have done wrong. I would be very grateful if someone points out a fix.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
char* buffer = (char*)malloc(*argv[1]); // Allocate memory
if(buffer=NULL) // if *argv[1] is not existed, exit the program
exit(1);
int n = 0;
FILE* fp=fopen("file.txt","r"); // Open the file
do {
buffer[n] =fscanf(fp,"%c",buffer); // read from file until it gets EOF
} while(buffer[n] != EOF);
fclose(fp); // Close the file
printf("%s",buffer); // Print the stored string
free(buffer); // Return the memory
return 0;
}
Got it. This:
if(buffer=NULL)
should be this:
if(buffer==NULL)
You're setting buffer to NULL. I'm sure you can see what happens next.
More generally, this code is trying to do several things, and it's full of bugs. You should have tested the different functions separately and worked out those bugs along the way.
This here seems wrong:
char* buffer = (char*)malloc(*argv[1]);
The command line argument is a string, but you want a number. You have to convert the string to a number first.
Another problem: In your loop n is never increased, which is why only the first byte of the buffer is written.
Please find the fixed code and the comments inline:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
// Add the check if *argv[1] does not exist, exit the program
long mem_sz=strtol(argv[1],NULL,10);//Safer to atoi
char* buffer = (char*)malloc(mem_sz); // properly allocate memory
//You missed the == in the NULL check.
if(buffer==NULL)
exit(1);
int n = 0;
FILE* fp=fopen("file.txt","r"); // Open the file
if (fp == NULL)//Check fp too
exit(1);
do
{
buffer[n++]=fscanf(fp,"%c",buffer);
} // read from file until it gets EOF and n++
while(buffer[n-1] != EOF);//Check the last read character
buffer[n]=0;//Put an end of string, so that printf later will work correct
fclose(fp); // Close the file
printf("%s\n",buffer); // Print the stored string
free(buffer); // Return the memory
return 0;
}
hi i have the following code below, where i try to get all the lines of a file into an array... for example if in file data.txt i have the following:
first line
second line
then in below code i want to get in data array the following:
data[0] = "first line";
data[1] = "second line"
My first question: Currently I am getting "Segmentation fault"... Why?
Exactly i get the following output:
Number of lines is 7475613
Segmentation fault
My second question: Is there any better way to do what i am trying do?
Thanks!!!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
FILE *f = fopen("data.txt", "rb");
fseek(f, 0, SEEK_END);
long pos = ftell(f);
fseek(f, 0, SEEK_SET);
char *bytes = malloc(pos);
fread(bytes, pos, 1, f);
int i =0;
int counter = 0;
for(; i<pos; i++)
{
if(*(bytes+i)=='\n') counter++;
}
printf("\nNumber of lines is %d\n", counter);
char* data[counter];
int start=0, end=0;
counter = 0;
int length;
for(i=0; i<pos; i++)
{
if(*(bytes+i)=='\n')
{
end = i;
length =end-start;
data[counter]=(char*)malloc(sizeof(char)*(length));
strncpy(data[counter],
bytes+start,
length);
counter = counter+1;
start = end+1;
}
}
free(bytes);
return 0;
}
First line of the data.txt in this case is not '\n' it is: "23454555 6346346 3463463".
Thanks!
You need to malloc 1 more char for data[counter] for the terminating NUL.
after strncpy, you need to terminate the destination string.
Edit after edit of original question
Number of lines is 7475613
Whooooooaaaaaa, that's a bit too much for your computer!
If the size of a char * is 4, you want to reserve 29902452 bytes (30M) of automatic memory in the allocation of data.
You can allocate that memory dynamically instead:
/* char *data[counter]; */
char **data = malloc(counter * sizeof *data);
/* don't forget to free the memory when you no longer need it */
Edit: second question
My second question: Is there any
better way to do what i am trying do?
Not really; you're doing it right. But maybe you can code without the need to have all that data in memory at the same time.
Read and deal with a single line at a time.
You also need to free(data[counter]); in a loop ... and free(data); before the "you're doing it right" above is correct :)
And you need to check if each of the several malloc() calls succeeded LOL
First of all you need to check if the file got opened correctly or not:
FILE *f = fopen("data.txt", "rb");
if(!f)
{
fprintf(stderr,"Error opening file");
exit (1);
}
If there is error opening the file and you don't check it, you'll get a seg fault when you try to fseek on an invalid file pointer.
Apart from that I see no errors. Tried running the program, by printing the value of the data array at the end, it ran as expected.
One thing to note is that you're opening your file as binary - line termination disciplines may not work as you expect on your platform (UNIX is lf, Windows is cr-lf, some versions of MacOS are cr).