Why I got segmentation fault when using fgets in C? [closed] - c

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I run the program with this command:
./word_search oi < text.txt
and got segmentation fault when running it.
This program is aiming to find where the word (giving as command line arg) exists in a file and print out those lines.
#include <stdio.h>
#include "substring.c"
int main(int argc, char ** argv) {
if(argc == 2) {
char *str;
while(fgets(str, 100, stdin)) {
if(substring(str, argv[1]) != -1) {
printf("Found: %s", str);
}
}
}
return 0;
}
If I change char *str into char str[100] then it works pretty good. Could anyone please tell me why?
The contents in substring.c:
#include <stdio.h>
#include <string.h>
int substring(const char *line, const char *substr) {
int i, j;
int result;
for(i = 0; i <= strlen(line)-strlen(substr); i++) {
result = 0;
if(line[i] == substr[0]) {
int c = i;
for(j = 0; j < strlen(substr); j++) {
if (line[c] != substr[j]) {
result = -1;
}
c++;
}
if(result != -1)
return i;
}
}
return -1;
}
The contents in test.txt are just several lines of meaningless characters.

char *str is an unitialized pointer, it cannot hold the string you are trying to copy into it, either allocate memory to it:
#include <stdlib.h>
#define SIZE 100
char *str = malloc(SIZE); //char has the size of 1 across platforms
Or simply declare it with the size you need:
char str[SIZE];
Pass the size of str to fgets
while(fgets(str, SIZE, stdin))
Of fgets:
Your container will be null terminated, it can only hold a string of SIZE - 1 characters.
All characters above SIZE - 1, including '\n' will remain unread and therefore in the buffer, you might need to clear it.

I suggest you take some time to learn basic C. Especially read about pointers, they are bit hard to get right at first.
In your example, str is a pointer to an undefined memory location.

Related

Pthread program printing different values on Codeblocks and Linux Kernel [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm working on the following pthread program that finds the number of substrings in string2 that are in string1:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#define NUM_THREADS 4
#define MAX 1024
int n1,n2,i;
char *s1,*s2;
FILE *fp;
char *substring(char *string, int position, int length);
void *occurrence();
int readf(FILE *fp)
{
if((fp=fopen("strings.txt", "r"))==NULL){
printf("ERROR: can't open strings.txt!\n");
return 0;
}
s1=(char *)malloc(sizeof(char)*MAX);
if(s1==NULL){
printf("ERROR: Out of memory!\n");
return -1;
}
s2=(char *)malloc(sizeof(char)*MAX);
if(s1==NULL){
printf("ERROR: Out of memory\n");
return -1;
}
/*read s1 s2 from the file*/
s1=fgets(s1, MAX, fp);
s2=fgets(s2, MAX, fp);
n1=strlen(s1); /*length of s1*/
n2=strlen(s2)-1; /*length of s2*/
if(s1==NULL || s2==NULL || n1<n2) /*when error exit*/
return -1;
return 0;
}
int main(void)
{
pthread_t tid;
pthread_create(&tid, NULL, occurrence, NULL);
pthread_join(tid, NULL);
exit(0);
}
char *substring(char *string, int position, int length)
{
char *pointer;
int c;
pointer = malloc(length+1);
if (pointer == NULL)
{
printf("Unable to allocate memory.\n");
exit(1);
}
for (c = 0 ; c < length ; c++)
{
*(pointer+c) = *(string+position-1);
string++;
}
*(pointer+c) = '\0';
return pointer;
}
void* occurrence()
{
char *string1;
char *string2;
char *new_str;
int counter=0;
readf(fp);
string1 = s1;
string2 = s2;
new_str = malloc(200);
for(i=1;i<=strlen(string1);i++)
{
new_str = substring(string1,i,strlen(string2));
if(strcmp(new_str, string2)==0)
{
counter++;
}
}
printf("The number of substrings is: %d \n",counter);
return 0;
}
When i compile it on codeblocks, it prints the correct number of substrings. However, when I compile it on the Linux kernel, it always prints 1 as the number of substrings, even though there's more than one. For example, a strings.txt file that has abdeabjhab in the first line and ab in the 2nd line should print 3, since there's 3 instances of ab in the first line. My Linux kernel prints 1. Is there a specific way I'm supposed to compile it for it to print the right value? I'm current using gcc -pthread substring.c -o substrings to compile and ./substrings to execute it.
There are several issues here.
First the signature for occurrence is wrong; the thread function should take a void* as argument and return a void* as required by the pthread_create API. So it should be:
void *occurrence(void*);
and
void *occurrence(void arg*) {
...
return NULL;
}
There are several other questionable things in your code.
You are passing the global variable fp to readf() function. Why do you need to pass a global variable?
You are reading only the first two lines. What if the file contains many more lines?
Why do you have s1 and s2 as global? You could easily rewrite it to pass from readf back to occurrence. Or occurrence could pass varibles that readf writes into.
You don't close the file with fclose.
You create just one thread to do the work and the main thread just waits for it. So there's no real need for threads here. You might as well let the main thread do the work and not bother with threads.
Why do you subtract here?: n2=strlen(s2)-1; /*length of s2*/.
What if the length of s1 and s2 are the same? Is "abc" not a substring of "abc"?
Your actual of problem of getting incorrect substring count is probably because fgets() reads in the newline character and thus the substring match fails.
To remove newlines, you can do in your readf function after reading s1 and s2:
char *p = strchr(s1, '\n');
if (p) *p = 0;
p = strchr(s2, '\n');
if (p) *p = 0;
This should fix the immediate problem. But there's a lot you could improve.

Manipulation array in function - c - Segmentation fault

So I started to learn how to code a few weeks ago, and this site helped me so much, thank you for that. But this time I got stuck and canĀ“t really figure out why...Hope you can help me.
Basically I have a function prototype I have to use in my program and I have my troubles with it. The function should receive a string and then only copy every second char of that string and return the result...
This is what I've got so far:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define max_size 1000
char * everySecondChar(char * dest, char * input);
int main() {
char inputstr[max_size] = {0};
char *input[max_size] = {0};
char *dest[max_size] = {0};
char temp[max_size] = {0};
int i = 0;
while (fgets(inputstr, max_size, stdin) != NULL)
{
input[i] = strndup(inputstr, max_size);
strcat(temp,inputstr);
i++;
}
input[0] = strndup(temp, max_size);
printf("Inputted text:\n%s", *input);
printf("\n");
printf("\n");
printf("Resulting string:\n");
everySecondChar(*dest, *input);
printf("%s", *dest);
return 0;
}
char * everySecondChar(char * dest, char * input)
{
int i = 0;
for(i = 0; i < max_size; i+=2) {
strcat(dest,input);
}
return dest;
}
I know this is probably a 1-min challenge for the most of you, but I am having my troubles whenever I see those nasty * in a function prototype :(
Congrats on getting started with programming!
To your question: there's quite a few things that could be addressed, but since there seems to be some more basic confusion and misunderstanding, I'll address what makes sense given the context of your issue.
First, you're using strcat which concatenates strings (e.g. adds to the string), when you just need simple character assignment.
Next, you have a lot of pointers to arrays and there seems to be some confusion regarding pointers; in your main function, you don't need all of the temporary variables to do what you're wanting.
You could have simply:
char inputstr[MAX_SIZE] = {0};
char dest[MAX_SIZE] = {0};
You could have less (realistically) but we'll stick with the basics for now.
Next, you're looping to get user input:
while (fgets(inputstr, max_size, stdin) != NULL)
{
input[i] = strndup(inputstr, max_size);
strcat(temp,inputstr);
i++;
}
Here, you don't check if i exceeds max_size which your input variable has been allocated for; if i exceeds max_size when you go to assign input[i] to the memory location returned by strndup (which calls malloc), you are writing beyond your memory bounds, which is also known as a buffer overflow. This is potentially where your segmentation fault is happening. You could also have some issues when you do strcat(temp,inputstr); since strcat:
Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination.
If you're simply just trying to get what the user entered, and print every 2nd character with your function, you don't need to loop:
if (fgets(inputstr, MAX_SIZE, stdin) != NULL) {
everySecondChar(dest, inputstr);
printf("Inputted text:\n%s\n\nResulting string:\n%s\n", inputstr, dest);
}
Lastly, in your everySecondChar function, you're using strcat again when all you need to do is simple assignment (which does a 'copy'):
char * everySecondChar(char * dest, char * input)
{
int i, j;
for(i = 0, j = 0; i < MAX_SIZE; ++i, ++j) {
if (input[i] == 0) break; // end if string?
dest[j] = input[i++];
}
return dest;
}
Putting all of it together, you get:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_SIZE 1000
char * everySecondChar(char * dest, char * input);
int main(void)
{
char inputstr[MAX_SIZE] = {0};
char dest[MAX_SIZE] = {0};
printf("Enter some text: ");
if (fgets(inputstr, MAX_SIZE, stdin) != NULL) {
everySecondChar(dest, inputstr);
printf("Inputted text:\n%s\n\nResulting string:\n%s\n", inputstr, dest);
}
return 0;
}
char * everySecondChar(char * dest, char * input)
{
int i, j;
for(i = 0, j = 0; i < MAX_SIZE; ++i, ++j) {
if (input[i] == 0) break; // end if string?
dest[j] = input[i++];
}
return dest;
}
That aside, I'll address some other things; typically if you have a constant value, like your max_size variable, it's considered "best practice" to capitalize the entire thing:
`#define MAX_SIZE 1000`
I am having my troubles whenever I see those nasty * in a function prototype :(
Those nasty *'s in your function prototype (and variable declarations) are known as a pointer qualifier; it indicates that the type of the variable is a pointer to the type specified. A pointer isn't something to be scared of, you're learning C, it's highly important you understand what a pointer is and it's utility.
I won't dive into all of the specificities of pointers, aliases, etc. etc. since that is beyond the scope of this Q&A, but WikiBooks has a great intro and explanation covering a lot of those concepts.
Hope that can help!

Replicating the Strlen function in C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have been working on my C assignment where I try to replicate strlen() function without actually using it. This is the code I have been trying to get working. However, somehow the main function does not reflect what's happenning in mystrlen() function. Can you please tell me why it does not work as the strlen() function?
#include <stdio.h>
int mystrlen(char *input_string) {
/* This function returns the length of the input string */
/* WRITE FUNCTION CODE HERE! */
char str1[50];
int abcd = 0;
scanf("%s", str1);
int m;
for(m=0; str1[m]; m++){
abcd ++;
}
return 0;
}
int main(int argc, char **argv) {
int length;
if (argc!=2) {
printf("Usage: strlen <input_string_with_no_space_inside_it>\n\n");
return 1;
}
length = mystrlen(argv[1]);
printf("The length is: %d characters.\n",length);
return 0;
}
This:
return 0;
should be:
return abcd;
That said, abcd is a terrible name for this variable, and the function makes little sense as a strlen() replacement. It doesn't touch its argument, and calls scanf() to read input from the user, which you really don't want a strlen() replacement to do.
Here's one way of writing it:
size_t mystrlen(const char *s)
{
size_t len = 0;
if(s != NULL)
{
while(*s != '\0')
{
++len;
++s;
}
}
return len;
}
Improvements include:
Proper size_t-typed return value (lengths are sizes, and cannot be negative) so size_t is proper and what the real strlen() uses.
Doesn't do any input-reading.
Uses the input argument.
Computes length and returns it.
It also handles being given NULL, as a bonus.
A matching main() that does what yours did could be:
int main(int argc, char **argv)
{
if (argc != 2)
{
printf("Usage: strlen <input_string_with_no_space_inside_it>\n\n");
return 1;
}
const size_t length = mystrlen(argv[1]);
printf("The length is: %zu characters.\n", length);
return 0;
}
This basically centers around the int-to-size_t change. Also note that in shells supporting quoting, you can run your program like this:
$ ./strlen "hello this is a string with spaces in it"
and it will pass that entire quoted string (sans quotes, of course) in argv[1].
First of all, you try to pass a string, and then you invoke scanf function in mystrlen. Delete this scanf.
Secondly, your function always returns zero instead of value of variable abcd.

Problems with reversing line into file [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
This code does reverse and put result in file, but not fully correct.
Like, some issues with detecting line breaker or sth. Here's an example:
Source:
This is a line.
This is another line.
Quick brown fox jumps over a lazy dog!
Result:
(blank line)
.enil a si sihT
.enil rehtona si sihT!god yzal a revo spmuj xof nworb kciuQ
#include <stdio.h>
#include <string.h>
char *reverse (char *str)
{
char *begin, *end, c;
if (!str || !(*str))
return NULL;
for (begin=str, end=str+strlen(str)-1; begin<end; begin++, end--)
{
c=*begin;
*begin=*end;
*end=c;
}
begin=str+strlen(str)+1; *begin='\0'; //??
return str;
}
void main(void)
{
char line[1000];
FILE *fsrc, *frslt;
fsrc=fopen("source.txt", "r");
if (fsrc==NULL) return;
frslt=fopen("result.txt", "w");
while (!feof(fsrc))
{
fgets (line, 1000, fsrc);
fputs (reverse(line), frslt);
}
fclose(fsrc);
fclose(frslt);
}
A couple of comments/nitpicks, which may or may not solve your problem :)
if (!str || !(*str))
return NULL;
Don't do that. Don't return NULL on empty strings, fputs() will barf. In my experience, it's better to a) assert that the str pointer is non-null, b) return the empty string.
begin=str+strlen(str)+1; *begin='\0'; //??
There should be no need to terminate the string, since it's already terminated.
void main(void)
Nah, main() returns an int.
while (!feof(fsrc))
This won't work. You need to do some IO before you can test for feof()/ferror(). IMHO it's better to simply loop on fgets().
while (fgets(line, sizeof line, fsrc) {
...
}
It may be a good idea to drop the input and output files, and simply read from stdin and write to stdout, at least while testing. The functionality you're trying to implement is already available in a UNIX shell (man rev). Using stdin/stdout makes it easier to test and compare results with the results from rev.
Also, keep in mind that fgets() won't remove the \n from the string. input like "foo\n" becomes "\noof", which is probably not what you want.
Here's a snippet which illustrates my comments in code. It doesn't solve all problems, but should be sufficient to get you going.
#include <stdio.h>
#include <string.h>
#include <assert.h>
void reverse(char *str)
{
char *begin, *end, c;
size_t n;
assert(str != NULL);
n = strlen(str);
if (n == 0)
return;
for (begin = str, end = str + n - 1; begin < end; begin++, end--) {
c = *begin;
*begin = *end;
*end = c;
}
}
int main(void)
{
char line[1000];
while (fgets(line, sizeof line, stdin)) {
reverse(line);
fputs(line, stdout);
}
}
HTH

How do I compare and decrypt md5 password hashes in C? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
This program is for comparing password hashes. I am getting it to say Reading (filename), but then I get a segmentation fault (core dumped) error. I believe something is wrong in my main or readfile function. Is fscanf causing the problem here? And what is the middle argument in the for loop in main, i believe it would be number of lines, correct? I hav eprovided comments for better direction.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "crypt.h"
int tryguess(char *hash, char *guess)
{
// Extract the salt from the hash
char *salt;
memcpy(salt, &hash[3], 8);
salt[8] = '\0';
// Hash the guess using the salt
char *hashGuess = md5crypt(guess, salt);
// Compare the two hashes
if (strcmp(hashGuess, hash) == 0)
{
return 1;
}
else
{
return 0;
}
}
// Given a hash and a dictionary of guesses,
// try all guesses and return the matching guess.
char *crack(char *hash, char *dict[])
{
int i = 0;
while (dict[i])
{
if (tryguess(hash, dict[i])) return dict[i];
i++;
}
return NULL;
}
// Read in a file.
// The first line of the file is the number of lines in the file.
// Returns an array of strings, with the last element being a NULL
// indicating the end of the array.
char **read_file(char *fname)
{
char **dict;
printf("Reading %s\n", fname);
FILE *d = fopen(fname, "r");
if (! d) return NULL;
// Get the number of lines in the file
char *size;
fscanf(d, "%s[^\n]", size);
int filesize = atoi(size);
// Allocate memory for the array of strings (character pointers)
dict[0] = malloc(100 * sizeof(char *));
// Read in the rest of the file, allocting memory for each string
// as we go.
int count = 0;
int index = 0;
while (count < filesize)
{
for (int i = 0; dict[i] != NULL; i++)
{
fscanf(d, "%s[^\n]\n", dict[i]);
if (dict[i+1] != NULL)
{
dict[i+1] = malloc(1000);
}
count++;
index++;
}
}
// NULL termination. Last entry in the array should be NULL.
dict[index] = NULL;
printf("Done\n");
fclose(d);
return dict;
}
int main(int argc, char *argv[])
{
if (argc < 2)
{
printf("Usage: %s hash_file dict_file\n", argv[0]);
exit(1);
}
char **dictionary = read_file(argv[2]);
char **hashes = read_file(argv[1]);
// For each hash, try every entry in the dictionary.
// Print the matching dictionary entry.
for (int i = 0; i < (# of lines); i++)
{
char *hash = hashes[i];
char *result = crack(hash, dictionary);
printf("%s", result);
}
}
One problem I see is this (which can be causing segmentation fault):
// Extract the salt from the hash
char *salt;
memcpy(salt, &hash[3], 8);
salt[8] = '\0';
You can't write anything to salt, because it is just pointer,
no memory allocation has been done.
You can declare it on stack, if you know it's max size for instance, e.g., char salt[16];.
Usage is also similar: memcpy(salt, &hash[3], 8);
The segmentation fault (core dumped) is an error you get when:
By addressing non-existent/allocated memory.
Trying to read from an illegal memory location will cause this fault. i.e.
If you fopen a file, it fails and the file pointer returned is NULL and you try to read from that file pointer. This will give you a segmentation fault.
dict[i] = string;
dict = malloc(1000);
In what world do these two lines make sense together? You set a pointer (to a stack allocated string!) then you ignore your prior buffer, dict, in favor of a new one. These pointer errors need fixed!

Resources