Segmentation fault Ubuntu C - c

I am getting a segmentation fault when I want to run this program. It is supposed to by a self-written grep function but case-insensitive. The same code for case-sensitive works just fine so it might have something to do with tolower()?. Please help.
Used VS code in Ubuntu on a Windows PC.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main (int argc, char *argv[]) {
if (argc > 3) {
printf("Too many arguments. Only use 2: your search string and the file name.");
return -1;
}
//FILE * fp;
FILE * fp = fopen(argv[2], "r");
if(fp == NULL) {
perror("Unable to open file!");
return -1;
}
char * buffer = NULL;
size_t bufsize = 0;
char * lowerBuffer = malloc(sizeof(strlen(buffer)));
for (int i = 0; buffer[i] != '\0'; i++) {
lowerBuffer[i] = tolower(buffer[i]);
}
printf("tolower: %s", lowerBuffer);
while (getline(&buffer, &bufsize, fp) != -1) {
if (strstr(buffer, argv[1]))
{
printf("%s", buffer);
}
//printf("%zd", strlen(buffer));
}
fclose(fp);
free(buffer);
//getline();
return 0;
}
Compiled with gcc mygrepin.c, run with ./a.out test test.txt.
This is what my test.txt looks like:
hallo das ist ein Test.
test
test
test
test
test
I am expecting this output for this command ./a.out test test.txt:
hallo das ist ein Test.
test
test
test
test
test

You try to use
malloc(sizeof(strlen(buffer)))
on an object you just defined as Null
char * buffer = NULL;
Malloc is used to allocate space. What you want to do is to allocate space for the size of a string with the length of your variable buffer. Buffer is null.
Edit: As a comment pointed out not no space is allocated. It is either 4 or 8 depending on your machine. It works on the type. A pointer should return the value of 4 or 8 depending on your architecture of the system. Thanks to #mch for pointing that out. Even though this is true, the problem still remains and was caused by the buffer never being set to a value besides NULL.

Related

C Using char* in fscanf causing error Segmentation fault: 11

I am new to C and I came across an issue when using fscanf to read all strings from a .txt file.
The code is as follow:
#include <stdlib.h>
#include <stdio.h>
int main() {
FILE *spIn;
char *numIn;
spIn = fopen("data.txt", "r");
if (spIn == NULL) {
printf("Can't Open This File \n");
}
while ((fscanf(spIn, "%s", numIn)) == 1) {
printf("%s\n", numIn);
};
fclose(spIn);
return 1;
}
This throws an error: Segmentation fault: 11.
The original data on txt file is:
1 2 345 rrtts46
dfddcd gh 21
789 kl
a mix of ints, strings, white space and newline characters.
At least 4 candidate undefined behaviors (UB) that could lead to a fault of some kind.
Code fails to pass to fscanf(spIn,"%s",numIn) an initialized pointer.
Code calls fscanf() even if fopen() fails.
Code calls fclose() even if fopen() fails.
No width limit in fscanf(spIn,"%s",numIn)), worse than gets().
Text files really do not have strings ('\0' terminated data) nor int, they have lines (various characters with a '\n' termination).
To read a line in and save as a string, use fgets(). Do not use fscanf() to read lines of data.
#include <stdlib.h>
#include <stdio.h>
int main() {
FILE *spIn = fopen("data.txt", "r");
if (spIn == NULL) {
printf("Can't Open This File \n");
} else {
char buf[100];
while (fgets(buf, sizeof buf, spIn)) {
printf("%s", buf);
}
fclose(spIn);
}
}
char* numIn is a pointer, and it is uninitalized, you can't really store anything in it, you need to either allocate memory for it or make it point to some valid memory location:
#include<stdlib.h> // for malloc
char* numIn = malloc(100); // space for 99 char + null terminator byte
//...
while ((fscanf(spIn, "%99s", numIn)) == 1)
{
printf("%s\n",numIn);
};
Or:
char str[100];
char *numIn = str;
Which in this small code makes little sense, you should probably make numIn a fixed size array to begin with:
char numIn[100];
Note that that you should use a width specifier in *scanf to avoid buffer overflow. This still has a problem though, it will read word by word, instead of line by line.
Looking at your input file, using fgets seems like a better option, it can read complete lines, including spaces:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE *spIn;
char numIn[100];
spIn = fopen("data.txt", "r");
if (spIn != NULL)
{
while ((fgets(numIn, sizeof numIn, spIn)))
{
numIn[strcspn(numIn, "\n")] = '\0'; // removing \n
printf("%s\n", numIn);
}
fclose(spIn);
}
else
{
perror("Can't Open This File");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Since fgets also parses the \n character, I'm removing it with strcspn.
Though you do verify the return value of fopen the execution continues even if it fails to open, I also addressed that issue.

How to fix the segmentation fault error 11 appearing after running my code?

I'm trying to solve this question regarding moving data from a file to another in C. Running the program gives a segmentation error 11. I've attached a picture of the question. Exercise 4
I believe there is a problem in opening the files, I entered inside the terminal the C code script name: code.c file1.txt file2.bin -b. The files are included in the path.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char** argv){
size_t k;
char read1[100] = {};
FILE* s;
FILE* d;
if (argc < 4) {
printf("NA");
exit(1);
}
if (strcmp(argv[4], "-b") == 0) {
printf("binary file output\n");
d = fopen(argv[3], "wb");
if (d == NULL) {
printf("cant open d");
exit(1);
}
} else {
if (strcmp(argv[4], "-t") == 0) {
printf("textual file output\n");
d = fopen(argv[3], "w");
} else {
printf("error");
exit(1);
}
}
s = fopen(argv[2], "r");
if (s == NULL) {
printf("cant open s");
exit(2);
}
k = fread(read1, sizeof(char),100, s);
while (k != 0) {
fwrite(read1, k,1, s);
k = fread(read1, sizeof(char),100, s);
}
fwrite(read1, k,1, s);
fclose(s);
fclose(d);
return 1;
}
I expect to move all the data from file 1 to file 2, and file2 output can be binary or textual depending on the user input stream. Ignored the 'hexadecimal' case.
You seem to want to write a program that takes the name of an input file, an output file and a flag (-b or -t), so I guess you're calling your program like this:
program infile outfile [-b|-t]
Those are 3 arguments. They will be argv[1], argv[2] and argv[3] respectively. You should not access argv[4]. Your program will segfault on strcmp(argv[4], "-b"). All your argv[x] should be shifted back by one. The check if (argc < 4) is ok though.
Another thing that can cause segmentation fault is reading from a FILE* that is not valid. You're not checking if d == NULL after the second fopen(). You should do that, and exit with an error in case it's NULL.
Other than this, other problems with your code are:
You should not call fwrite after exiting the while loop. You know that k == 0 when out of the loop. It is not harmful, but it's useless and will print nothing.
You should reorder the arguments of fwrite like this: fwrite(read1, 1, k, s).
Your last return 1 statement makes no sense, you should return 0, not 1, for sucessful program execution.
You don't need to initialize the array with char read1[100] = {}; since you don't use it before overwriting its content. Doing char read[100]; is just fine.
PS: you should learn to use GDB to debug your programs. Problems like this one are very easy to spot using GDB by just stepping through the instructions one by one.

strstr() causing a segmentation fault error

The objective here is to take a whole text file that I dump into a buffer and then use the strcasestr() function to find the pointer of the word I am looking for within my buffer. It constantly gives me the segmentation fault error. At first, I thought it may be size so I tried with smaller sizes but it doesn't work either. The function only works with strings I create inside the actual code (ex : char * bob = "bob"; char * bobsentence = "bob is cool"; strstr(bobsentence, bob);). Which leads me to believe it has something to do with the fgets(). Any help is appreciated, really stuck on this one.
#define _GNU_SOURCE //to use strcasestr
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void textEdit(char *path, char *word){
printf("%s\n", path);
FILE *textFile;
//FILE *locationFile;
//FILE *tempFile;
char counter[1024];
int count = 0;
textFile = fopen(path, "r+");
//locationFile = fopen(path, "r+");
//opens file to read and write and opens temp file to write
if( textFile == NULL){ //|| tempFile == NULL || locationFile == NULL) ) {
printf ("\nerror\n");
return;
}
// SECTION : ALLOCATES MEMORY NEEDED FOR COPY TEXT IN ARRAY
// finds number of lines to estimate total size of array needed for buffer
while((fgets(counter, sizeof(counter), textFile)) != NULL){
count++;
}
fclose(textFile);
FILE *tempFile = fopen(path, "r+");
count *= 1024;
printf("%d %zu\n",count, sizeof(char));
char *buffer = malloc(count); //1024 is the max number of characters per line in a traditional txt
if(buffer == NULL){ //error with malloc
return;
}
// SECTION : DUMPS TEXT INTO ARRAY
if(fgets(buffer, count, tempFile) == NULL){
printf("error");
} //dumps all text into array
printf("%s\n", buffer);
char * searchedWord;
while((searchedWord = strcasestr(buffer, word)) != NULL){
}
fclose(tempFile);
//fclose(locationFile);
free(buffer);
}
It looks that you forgot to initialize count variable to 0:
int count = 0;
You increment it and it can contain any random value, even negative.
Also, note that your utilization of strstr doesn't look correct. The function returns the pointer to first occurrence that matches. Note, that it doesn't remember already found matches, so if match exists it should loop forever in this loop. Instead it should look like:
char *pos = buffer;
while((pos = strcasestr(pos, word)) != NULL){
searchedWord = pos;
/* do something with searchedWord but remember that it belongs to
allocated buffer and can't be used after free() */
pos++;
}

Why am I getting a hyphen at start of file?

I am learning C and I have tried to build a program that outputs its own source. This is my source:
#include <stdio.h>
int S = 512;
int main(){
FILE * fp;
fp = fopen("hello.c","r");
char * line = (char *) malloc(S);
int i = 0;
while (i == 0)
{
i = feof(fp);
printf("%s",line);
fgets(line,S,fp);
}
fclose(fp);
}
I have used the tcc compiler and I got this output:
But notice, I got a hyphen before #include. The rest of the output is correct.
So please can someone explain why I got this hyphen??
You're printing the first line before you've read anything.
#include <stdio.h>
int main(){
FILE *fp = fopen("hello.c", "r");
char line[256];
while (fgets(line, sizeof line, fp) != NULL)
printf("%s",line);
fclose(fp);
return 0;
}
#ooga gave you the correct answer.
The why is that malloc doesn't initialize the memory before it returns it to you, unlike its sister calloc.
Most likely, on another platform / compiler, you'd get something different.
Some compilers use a debug heap that initializes "unitialized" memory to a specific value. The release mode will probably result in random garbage instead of a '-' everytime.

fgets in C doesn't return a portion of an string

I'm totally new in C, and I'm trying to do a little application that searches for a string in a file. My problem is that I need to open a big file (more than 1GB) with just one line inside and fgets return me the entire file (I'm doing test with a 10KB file).
Actually this is my code:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *search = argv[argc-1];
int retro = strlen(search);
int pun = 0;
int sortida;
int limit = 10;
char ara[20];
FILE *fp;
if ((fp = fopen ("SEARCHFILE", "r")) == NULL){
sortida = -1;
exit (1);
}
while(!feof(fp)){
if (fgets(ara, 20, fp) == NULL){
break;
}
//this must be a 20 bytes line, but it gets the entyre 10Kb file
printf("%s",ara);
}
sortida = 1;
if(fclose(fp) != 0){
sortida = -2;
exit (1);
}
return 0;
}
What can I do to find an string into a file?
I've tried with GREP but it don't helps, because it returns the position:ENTIRE_STRING.
I'm open to ideas.
Try
printf("%s\n",ara);
Also consider initializing variables before you use them:
char ara[20]={0x0};
You only allocated 20 bytes for the input buffer, but told the fgets to read 20 bytes.
Make this change:
if (fgets(ara, sizeof(ara)-1, fp) == NULL){
remember, if you want 20 characters PLUS the trailing '\0' that marks the end of the string you have to allocate 21 bytes.

Resources