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.
Related
To study for the exam we are trying to do some exercise from past exams.
In this exercise we get a header file and we have to create a function that read an input file and print onto the stdout only the parts of strings that do not contain digits.
(We have to pass the pointer of the string red to the main function).
We tried to do it with a an array but when printing the first word is empty or has strange characters. Instead doing a malloc allocation works fine.
What is also strange is that printing before everything an empty string will fix the code.
Therefore we don't understand why using an array of char the first word is not printed correctly, although it is saved in the buffer.
Including a printf before the while loop in the main function will reset the problem.
Using dynamic allocation (malloc) and not static allocation (array) will fix the print.
Iterating over the whole array and set all the memory to 0 does not fix the problem.
Therefore the pointer is correct as with printing an empty string it prints it correctly, but I really cannot understand what cause the issue.
Question are:
How it is possible that printing an empty string the print is correct?
Array is allocated on the stack therefore it is deallocated when the program exit the scope, why is only the first broken and not all the words?
#include "word_reader.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
const char * read_next_word(FILE * f) {
char buffer[WORD_MAX_LEN];
char * word = buffer;
for (int i = 0; i < WORD_MAX_LEN; ++i)
buffer[i] = 0;
//char * buffer = malloc(sizeof(char) * WORD_MAX_LEN);
int found = 0;
int c = 0;
int i = 0;
while (!found && c != EOF) {
while ((c = fgetc(f)) != EOF && isalpha(c)) {
found = 1;
buffer[i] = c;
++i;
}
buffer[i] = '\0';
}
if (found) {
return word;
//return buffer; // when use malloc
}
return 0;
}
int main(int argc, char * argv[]) {
FILE * f = fopen(argv[1], "r");
if(!f) {
perror(argv[1]);
return EXIT_FAILURE;
}
const char * word = 0;
//printf(""); // adding this line fix the problem
while ((word = read_next_word(f))) {
printf("%s\n", word);
}
fclose(f);
return 0;
}
the header file contain only the read_next_word declaration and define WORD_MAX_LEN to 1024. (Also include
the file to read (a simple .txt file)
ciao234 44242 toro
12Tiz23 where333
WEvo23
expected result:
ciao
toro
Tiz
where
WEvo
actual result
�rǫs+)co�0�*�E�L�mзx�<�/��d�c�q
toro
Tiz
where
WEvo
the first line is always some ascii characters or an empty line.
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!
i am new in programming and in stackoverflow that is why i sometime maybe can have simple questions when i code something and want to get input fromthe file`
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int len1=0;
FILE* p;
char a;
char b[10];
p = fopen(argv[1],"r");
while (1)
{
a = fgetc(p);
if(a == ' ') break;
else
{
len1++;
b[len1-1] = a;
}
}
printf("%c\n", b0);
return 0;
}
it gives segmentation fault and what is the reason?
You have a buffer overrun. If you change your while loop to stop after reading ten characters, even if space has not been reached, you should do fine.
Additionally, you are passing a character at b[len1] into printf, and have it interpreted as a pointer. This will segfault no matter what.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int len1=0;
FILE* p;
char a;
char b[10+1]; // <<== need one more byte for the terminator
if (argc != 2)
{
fprintf(stderr, "Need to supply a filename\n");
return (-1);
}
p = fopen(argv[1],"r");
if (p == NULL)
{
fprintf(stderr, "Cannot open file %s\n", argv[1]);
return(-2);
}
while (len1 < 10) // <<== avoid buffer overruns
{
a = fgetc(p);
if(a == ' ') break;
else
{
len1++;
b[len1-1] = a;
}
}
b[len1] = '\0'; // <<== Don't forget to zero-terminate
printf("%s\n", b); // <<== Pass the buffer, not the last character from it
return 0;
}
char b[10] only has 10 elements. len1 is incremented every iteration of an infinite loop. This quickly becomes > 10. Eventually somewhere past 10 you write into some memory you don't have access too. Hence the seg fault.
Instead of the while (1), you should test the loop index against the size of your table b (so 10)
What do you want to do exactly ?
You have two problems
What happens when you read the file and the first 10 characters are not a space? The array b will be esxhausted.
printf is trying to print a string. b[len1] is a character.
There are two logical bugs in your program ::
1.while(1) you are having an non-terminating loop, it will result into stackoverflow.
2. char b[10] here, b is a char array of size 10 i.e. b[0] to b[9], but as in your program len1++ is executing for every iteration, which will access memory beyond b[9].
To overcome these issues use while(len1<10).
this problem I think is solely a lack of memory allocation issue.
(maybe skip to the bottom and read the final question for some simple suggestions)
I am writing this program that reads file(s) entered by the user. If the file 'includes' other files, then they will be read also. To check if another file includes a file, I parse the first word of the string. To do this I wrote a function that returns the parsed word, and a pointer is passed in that gets set to the first letter of the next word. For example consider the string:
"include foo" NOTE files can only include 1 other file
firstWord == include, chPtr == f
My algorithm parses firstWord to test for string equality with 'include', it then parses the second word to test for file validity and to see if the file has already been read.
Now, my problem is that many files are being read and chPtr gets overwritten. So, when I return the pointer to the next word. The next word will sometimes contain the last few characters of the previous file. Consider the example files named testfile-1 and bogus:
Let chPtr originally equal testfile-1 and now consider the parsing of 'include bogus':
extracting firstWord will == include, and chPtr will be overwritten to point to the b in bogus. So, chPtr will equal b o g u s '\0' l e - 1. the l e - 1 is the last few characters of testfile-1 since chPtr points to the same address of memory each time my function is called. This is a problem for me because when I parse bogus, chPtr will point to the l. Here is the code for my function:
char* extract_word(char** chPtr, char* line, char parseChar)
//POST: word is returned as the first n characters read until parseChar occurs in line
// FCTVAL == a ptr to the next word in line
{
int i = 0;
while(line[i] != parseChar && line[i] != '\0')
{
i++;
}
char* temp = Malloc(i + 1); //I have a malloc wrapper to check validity
for(int j = 0; j < i; j++)
{
temp[j] = line[j];
}
temp[i+1] = '\0';
*chPtr = (line + i + 1);
char* word = Strdup(temp); //I have a wrapper for strdup too
return word;
So, is my problem diagnosis correct? If so, do I make deep copies of chPtr? Also, how do I make deep copies of chPtr?
Thanks so much!
If I understand this correctly you want to scan a file and when an 'include' directive is encountered you want to scan the file specified in the the 'include' directive and so on ad infinitum for any levels of include i.e. read one file which may include other files which may in turn include other files.....
If that is so (and please correct if I am wrong ) then this is a classic recursion problem. The advantage of recursion is that all variables are created on the stack and are naturally freed when the stack unwinds.
The following code will do this without any need for malloc or free or the need to make copies of anything:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INCLUDE "include"
#define INCOFFSET 7
static void
process_record (char *name, char *buf)
{
// process record here
printf ("%s:%s\n", name, buf);
}
// change this to detect your particular include
static int
isinclude (char *buf)
{
//printf ("%s:Record %s INCLUDE=%s INCOFFSET=%d\n", __func__, buf, INCLUDE,
// INCOFFSET);
if (!strncmp (buf, INCLUDE, INCOFFSET))
{
//printf ("%s:Record == include", __func__);
return 1;
}
return 0;
}
static int
read_file (char *name)
{
//printf ("%s:File %s\n", __func__, name);
FILE *fd = fopen (name, "r");
if (!fd)
{
printf ("%s:Cannot open %s\n", __func__, name);
return -1;
}
char buf[1024];
ssize_t n;
while (fgets (buf, sizeof (buf), fd))
{
size_t n = strcspn (buf, "\n");
buf[n] = '\0';
//printf ("%s:Buf %s\n", __func__, buf);
if (isinclude (buf))
{
read_file (buf + (INCOFFSET + 1));
}
else
{
process_record (name, buf);
}
}
fclose (fd);
return 0;
}
int
main (int argc, char *argv[])
{
int ret = read_file (argv[1]);
if (ret < 0)
{
exit (EXIT_FAILURE);
}
exit (EXIT_SUCCESS);
}
char* temp = Malloc(i + 1); //I have a malloc wrapper to check validity
for(int j = 0; j < i; j++)
{
temp[j] = line[j];
}
temp[i+1] = '\0'; <------- subscript out of range replace with temp[i] = '\0';
It isn't clear where your problem is. But you might use a tool to help locate it.
Valgrind is one such (free) tool. It will detect a variety of memory access errors. (It likely would not have found your temp[i+1]='\0' error because that isnt "very wrong").
Our CheckPointer tool is another tool. It finds errors Valgrind cannot (e.g., e.g., it should have found your buggy temp assignment). While it is commercial, the evaluation version handles programs of small size, which may work for you. (I'm at home and don't remember the limits).
I'm trying to write a program that takes in a plaintext file as it's argument and parses through it, adding all the numbers together and then print out the sum. The following is my code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
static int sumNumbers(char filename[])
{
int sum = 0;
FILE *file = fopen(filename, "r");
char *str;
while (fgets(str, sizeof BUFSIZ, file))
{
while (*str != '\0')
{
if (isdigit(*str))
{
sum += atoi(str);
str++;
while (isdigit(*str))
str++;
continue;
}
str++;
}
}
fclose(file);
return sum;
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Please enter the filename as the argument.\n");
exit(EXIT_FAILURE);
}
else
{
printf("The sum of all the numbers in the file is : %d\n", sumNumbers(argv[1]));
exit(EXIT_SUCCESS);
}
return 0;
}
And the text file I'm using is:
This a rather boring text file with
some random numbers scattered
throughout it.
Here is one: 87 and here is another: 3
and finally two last numbers: 12
19381. Done. Phew.
When I compile and try to run it, I get a segmentation fault.
You've not allocated space for the buffer.The pointer str is just a dangling pointer. So your program effectively dumps the data read from the file into memory location which you don't own, leading to the segmentation fault.
You need:
char *str;
str = malloc(BUFSIZ); // this is missing..also free() the mem once done using it.
or just:
char str[BUFSIZ]; // but then you can't do str++, you'll have to use another
// pointer say char *ptr = str; and use it in place of str.
EDIT:
There is another bug in:
while (fgets(str, sizeof BUFSIZ, file))
The 2nd argument should be BUFSIZ not sizeof BUFSIZ.
Why?
Because the 2nd argument is the maximum number of characters to be read into the buffer including the null-character. Since sizeof BUFSIZ is 4 you can read max upto 3 char into the buffer. That is reason why 19381 was being read as 193 and then 81<space>.
You haven't allocated any memory to populate str. fgets takes as its first argument a buffer, not an unassigned pointer.
Instead of char *str; you need to define a reasonably sized buffer, say, char str[BUFSIZ];
Because you've not allocated space for your buffer.
A number of people have already addressed the problem you asked about, but I've got a question in return. What exactly do you think this accomplishes:
if (isdigit(*str))
{
if (isdigit(*str))
{
sum += atoi(str);
str++;
while (isdigit(*str))
str++;
continue;
}
}
What's supposed to be the point of two successive if statements with the exact same condition? (Note for the record: neither one has an else clause).
You have declared char* str, but you have not set aside memory for it just yet. You will need to malloc memory for it.
Many memory related errors such as this one can be easily found with valgrind. I'd highly recommend using it as a debugging tool.
char *str;
str has no memory allocated for it. Either use malloc() to allocate some memory for it, or declared it with a predefined size.
char str[MAX_SIZE];
Your program has several bugs:
It does not handle long lines correctly. When you read a buffer of some size it may happen that some number starts at the end of the buffer and continues at the beginning of the next buffer. For example, if you have a buffer of size 4, there might be the input The |numb|er 1|2345| is |larg|e., where the vertical lines indicate the buffer's contents. You would then count the 1 and the 2345 separately.
It calls isdigit with a char as argument. As soon as you read any "large" character (greater than SCHAR_MAX) the behavior is undefined. Your program might crash or produce incorrect results or do whatever it wants to do. To fix this, you must first cast the value to an unsigned char, for example isdigit((unsigned char) *str). Or, as in my code, you can feed it the value from the fgetc function, which is guaranteed to be a valid argument for isdigit.
You use a function that requires a buffer (fgets) but you fail to allocate the buffer. As others noted, the easiest way to get a buffer is to declare a local variable char buffer[BUFSIZ].
You use the str variable for two purposes: To hold the address of the buffer (which should remain constant over the whole execution time) and the pointer for analyzing the text (which changes during the execution). Make these two variables. I would call them buffer and p (short for pointer).
Here is my code:
#include <ctype.h>
#include <stdio.h>
static int sumNumbers(const char *filename)
{
int sum, num, c;
FILE *f;
if ((f = fopen(filename, "r")) == NULL) {
/* TODO: insert error handling here. */
}
sum = 0;
num = 0;
while ((c = fgetc(f)) != EOF) {
if (isdigit(c)) {
num = 10 * num + (c - '0');
} else if (num != 0) {
sum += num;
num = 0;
}
}
if (fclose(f) != 0) {
/* TODO: insert error handling here. */
}
return sum;
}
int main(int argc, char **argv) {
int i;
for (i = 1; i < argc; i++)
printf("%d\t%s\n", sumNumbers(argv[i]), argv[i]);
return 0;
}
Here is a function, that does your job:
static int sumNumbers(char* filename) {
int sum = 0;
FILE *file = fopen(filename, "r");
char buf[BUFSIZ], *str;
while (fgets(buf, BUFSIZ, file))
{
str=buf;
while (*str)
{
if (isdigit(*str))
{
sum += strtol(str, &str, 10);
}
str++;
}
}
fclose(file);
return sum;
}
This doesn't includes error handling, but works quite well. For your file, output will be
The sum of all the numbers in the file is : 19483