too many open files c - c

I have been trying to create a simple program. However, I encountered an error:
gmon.out:too many open files
I am not clear on why it says I have "too many open files". It does not appear I am using files.
#include<stdio.h>
#include<ctype.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>
struct position
{
int line;
int place;
struct position *next;
};
struct file
{
struct position *info;
struct file *next;
char *name;
};
struct word
{
char *name;
struct word *right;
struct word *left;
struct file *result;
};
int main()
{
int i;
struct word *d,*c;
char *s="brutus";
printf("%s",s);
c=(struct word*)malloc(sizeof(struct word));
strcpy(c->name,s);
c->left=NULL;
c->right=NULL;
for(i=1;i<=10;i++)
{
d=(struct word*)malloc(sizeof(struct word));
if(d==NULL)
exit(0);
scanf("%s",s);
printf("4");
s=d->name;
printf("%s",d->name);
d->left=NULL;
d->right=NULL;
}
system("pause");
exit(0);
}
What should I do about it?Thank you in advnace for your time!

First off:
gmon.out:too many open files
Means that you're compiling with the -p flag (profiling). gmon.out is the default file-name used by gprof. Just ditch-the-switch, and you won't get that problem anymore.
Of course, not profiling code isn't great, but you'd do well to address a coupe of issues first, before setting about actually profiling your code.
Some of these, quite numerous, issues are:
char *s="brutus";
printf("%s",s);
c=(struct word*)malloc(sizeof(struct word));
strcpy(c->name,s);
List of issues:
char *s should be const char *s, because it points to read-only memory.
Next, Do not cast the return of malloc
Check the return value of functions like malloc, they tell you something
struct wordis a struct of which all members are pointers. After allocating the struct, those pointers are invalid: you need to allocate memory for those members, too
strcpy expects the destination (c->name) to be a valid pointer, as I explained above: this is not the case here
What, then, should this code look like:
const char *s = "brutus";
c = malloc(sizeof *c);
if (c == NULL)
{
fprintf(stderr, "Could not allocate memory for struct word\n");
exit( EXIT_FAILURE );
}
//allocate enough memory to store the string
c->name = malloc(
(strlen(s)+1) * sizeof *c->name
);
//OR same, but shorter, works because the type char is guaranteed by the standard to be 1 byte in size
c->name = malloc(strlen(s)+1);
if (c->name == NULL)
exit( EXIT_FAILURE );//could not allocate mem
c->name[0] = '\0';//set to empty string, now we can use safer functions:
strncat(c->name, s, strlen(s));
After you address these issues, seriously re-think your approach, and ask yourself what it is you're actually trying to do here:
for(i=1;i<=10;i++)
{
d=(struct word*)malloc(sizeof(struct word));
if(d==NULL)
exit(0);
scanf("%s",s);
printf("4");
s=d->name;
}
You're allocating a struct 10 times, each time re-assigning it to d. You never free this memory, though. which is bad practice.
Again: don't cast the return of malloc, but that's the least of your worries.
if (d == NULL)
exit(0);
Ok, now you check the return of malloc. Great. But why on earth are you terminating with 0 (indicative of a successful run). There's a macro for this, too. You could've written:
if (d == NULL)
exit( EXIT_SUCCESS);
Clearly, EXIT_SUCCESS is not what you should communicate.
that const char *s is now being used to store user input. That's not going to work, though, as it points to read-only memory, so forget about the unsafe scanf("%s", s); statement. Use a stack variable, and make sure the input buffer is cleared, or use a safe alternative.
But then you go and do something as absurd as this:
s = d->name;
Again, d->name, like in the case with c, is an invalid pointer. Why assign it to s here? there's no point, no reason... only madness.
Bottom line: Kill this code before it hatches, start again, and please use these tips/recommendations and critiques as a guideline.

I have no idea why you're getting a 'too many open files', but this line:
strcpy(c->name,s)
is writing data to random memory, which could cause all kinds of problems.
You need to malloc() that c->name first.
Also that scanf to s looks suspicious, and d->name is never assigned anything either.
The reason that you're getting 'too many open files' is probably because some memory is getting overwritten in such a way that just happens to trigger that particular error. Welcome to the world of undefined behaviour. IE: If you overwrite random memory, basically anything can happen.

The first bug is in the line
strcpy(c->name,s);
At that point, c->name is an uninitialised pointer so the program will crash if you are lucky.
Reading your comment: You fixed the second bug. The first bug is still unfixed. And there's the third bug in the line
s=d->name;

This string copy will run off through memory, starting at whatever c->name points to until it finds a null terminator.
strcpy(c->name,s);
You have allocated space for c but not for the name pointer in c.
c->name = malloc([some length]);
c->name points somewhere, but you don't know where until you malloc it. That's why you're getting a seemingly random error, because your executing a string copy from an unknown location for an unknown number of bytes and you are clobbering whatever s points to for an unknown number of bytes.

Related

What i should use: strcpy or pointers?

typedef struct node{
char *name;
//etc...
}N
If i had char *string got from stdin and i wanted to pass it to N, i could do easily N->name=string, or it would be bettere to use strcpy?
which is more correct? which is more efficient? why?
You want to use a buffer to read your input from stdin. But if you don't make a copy, your string will be lost at the next read iteration. If you are going to allocate memory, and if you don't know the size of the string you receive, you should use a function like strdup instead of strcpy.
node->name = strdup(string_to_copy);
if (node->name == NULL)
printf("My allocation has failed!\n");
The allocated memory will have to be freed afterward. If the allocation fails, you will have a message (you should always check the success of your memory allocation).
If you don't want to allocate memory and if you know that the size of your input will never be higher than say, 100, you could get away with something like this:
typedef struct node{
char name[100];
//etc...
}N
In that case you could use the following. Note that strcpy is a dangerous function that should be used with extra-care:
strncpy(node->name, buffer, 100);
strcpy(node->name, buffer);
EDIT:
Here is a way to free your memory properly:
if (node->name != NULL)
{
free(node->name);
node->name = NULL;
}
This construction will free your memory and helps preventing double-free.
Answering "the result is the same, but what's the difference?" (from comment)
Starting from:
N *node = malloc(sizeof(N));
char input_from_stdin[80];
If we do
strcpy(node->name, input_from_stdin);
we invoke undefined behavior, but it might appear to work.
If we do
node->name = input_from_stdin;
than node->name only contains its expected value until input_from_stdin is reused, which is typically when the next line is read form input.
If we do
node->name = malloc(strlen(input_from_stdin) + 1);
strcpy(node->name, input_from_stdin);
we make a copy of the input that lives until we free it; but we must remember to free node->name before freeing node.
We can also do
typedef struct node{
char name[MAXSIZE];
//etc...
}N;
and then expect
strncpy(node->name, input_from_stdin, MAXSIZE-1)[MAXSIZE-1] = 0;
to work.
Some poeple do
strncpy(node->name, input_from_stdin, MAXSIZE);
which is valid but getting it back out again is touchier. This is rarely seen out of fixed-width records on disk now. We don't like MAXSIZE much anymore and prefer everything stretchy.

error while reading input from file c

I had been trying to read input from a file, but it seems that something doesn't work correctly...Instead of reading the word "Words" that exists in the text,the printf is always showing 2 additional random characters not included in the file...
The function is:
void search(struct word *w,FILE *f){
char *c;
char c2;
int i,j,k,l;
c=(char*)malloc(120*sizeof(char));
i=1;
while(f!=NULL) {
c2=fgetc(f);
while(c2!=EOF) {
while(c2!='\n') {
k=0;
while(c2!=' ') {
*(c+k)=c2;
k=k+1;
c2=getc(f);
}
if(w->name==c)
insert(i,j+1,name,&w);
}
memset(c, 0, sizeof(c));
j=j+k+1;
}
i=i+1;
}
}
}
the main function is
int main()
{
struct word *s;
s=(struct word*)malloc(sizeof(struct word));
s->name=(char*)malloc(20*sizeof(char));
s->result=NULL;
scanf("%s",s->name);
search(s);
printres(s);
system("pause");
exit(0);
}
and the structs are
struct position
{
char *filename;
int line;
int place;
struct position *next;
};
struct word
{
char *name;
struct word *right;
struct word *left;
struct position *result;
};
Why do these additional 2 characters appear? What should I do?
at first glance, this seems wrong to me
memset(c, 0, sizeof(c));
mainly because c it's a char*, then sizeof(c) will depend of compilation details...
And this test is wrong also:
if(w->name=c)
you probably want
if(strcmp(w->name,c) == 0)
after terminating the buffer by '\0'.
Also, you should check to not overflow your buffer, otherwise results will be unpredictable.
Indentation means you're not arranging your code in a properly readable manner.
I assume you're trying to store words line by line and word by word from a text file. But I'm unable to make out what your insert() function does. Besides, this code has a lot of faults.
I'll list them out first, and then you can state what you're exactly doing in this.
in main(): search(s)->file pointer parameter missing.
The prototype is : void search(struct word *w,FILE *f).
You have to do the following:
first open the file by using fopen() function.
use the pointer obtained from step i. and insert it as a parameter in your search() function.
This is just the solution I'm giving, you lack knowledge in this. You'll have to read a lot more on using files in c.
statement if(w->name=c):
It's "==" and not "=". Here you only assigned w->name as c.
You were trying to compare pointers and not the characters in them! Comparing pointers will be no use. You allocated different memory for both, how can the addresses be same? Read more on comparing strings in c.
Before comparing, you have to terminate a string with '\0'(null character). This often leads to unwanted characters being printed otherwise.
There'll be a lot of resources online which will have the exact answer to what you want to do. You can use a Google search. I can only point out so many faults, since your entire code has faults here and there. Learn more I'd say.
I haven't studied the logic of your code, so I'm just going to point out some of the problems:
c=(char*)malloc(120*sizeof(char));
The cast here is mostly useless. It can be used to warn you when you try to allocate data of the wrong type, but many people recommend the following way to allocate memory:
c = malloc (120 * sizeof *c);
This automatically allocates 120 items of the right size, regardless of the actual type of c. You should also check the return value of malloc(). Allocations can fail.
char c2;
c2=fgetc(f);
while(c2!=EOF) {
The fgetc() function returns a signed int representing a character in the range of an unsigned char, or EOF which is a negative value.
Plain char is either compatible with signed char or unsigned char. If it is unsigned, then it can never store the value of EOF, so the comparison c2 != EOF will always be false. If it is signed, then it can (typically, not necessarily) store EOF, but it will have the same value as an actual character.
You should store the return value of fgetc() in an int variable, compare it to EOF, and then convert it to char.
if(w->name==c)
Is this meant to be a string comparison? It doesn't work that way in C. You're only comparing pointers. To compare the actual strings, you'd have to call strcmp() or similar.
insert(i,j+1,name,&w);
(Undefined function)
memset(c, 0, sizeof(c));
I assume that you're trying to set the entire buffer to 0, but the size is wrong. This zeroes sizeof (char *) bytes, not the 120 bytes you allocated.
s=(struct word*)malloc(sizeof(struct word));
s->name=(char*)malloc(20*sizeof(char));
Pointless casts an no check for allocation failure. This should be (in my opinion):
s = malloc (sizeof *s);
if (s) {
s->name = malloc (20 * sizeof *s->name);
}
if (s && s->name) {
/* Go to work */
} else {
/* Allocation failure */
}
/* All done. Free memory. */
if (s) {
free (s->name);
}
free (s);
Because free(0) is a no-op, this cleanup works with all of the branches above.
search(s);
The search() function wants a second argument (FILE *).
printres(s);
(Undefined function)

Crashing when i put simple int variable

I have simple input function that works:
int main(void)
{
char *first;
char *last;
scanf("%s", first);
printf("%s", last);
return 1;
}
But when i start to expand my work, and put simple counter, programs crash:
int main(void)
{
int i = 0;
char *first;
char *last;
scanf("%s", first);
printf("%s", last);
return 1;
}
any idea ?
char *first;
scanf("%s", first);
first is not initialized before you call scanf: its value before the call is an invalid address.
You'll either want to dynamically allocate your char* before using scanf() to store into it or perhaps switch to a character array.
The problem is that first is an uninitialized pointer variable, meaning the pointer has an arbitrary value—it could be pointing anywhere in memory.
If you get very lucky, it ends up pointing to unused, allocated memory, so reading a string into it happens to work.
If you get lucky, it ends up pointing to an unmapped address, so reading a string into it causes a segfault.
If you get unlucky, it ends up pointing to some valid memory that holds something else, so it seems to work, but overwrites other data (or code), causing mysterious hard-to-debug crashes, incorrect results, or security holes.
Adding int i = 0; doesn't really change anything, except to "re-roll the dice". You could also get different results by, e.g., changing the compiler flags (especially if you turn debugging or optimization features on or off).
For example, maybe the area the stack gets allocated from looks like this when your main function is entered:
pointer to return address in the middle of libc
pointer to data segment
0
In the first version of your code, you don't initialize anything, and first ends up inheriting the value of the pointer to the data segment, so scanning into it works. In the second version, i ends up inheriting the pointer to the data segment (and overwriting it with 0), while first ends up inheriting the 0 value, so scanning into it segfaults.
If you're interested in seeing what's really going on, you can look at the assembly generated by the -S flag (or equivalent for your compiler), or you can just printf("%p\n", first) and then see what address you get and figure out what gets mapped there.
But really, it doesn't matter why it doesn't work. It's not supposed to work, and the only solution is to properly initialize the pointer to something valid (as ouah's answer and the others explain).
Your first variable is not initialized. Either declare it as array or allocate dynamically based on your need.
Array version,
int main(void)
{
char first[ SIZE ]; // define SIZE as per your need
char last[ SIZE ];
scanf("%s", first);
printf("%s", last); // FIXME : last is again not initialized
return 1;
}
Dynamic version,
int main(void)
{
char *first = malloc( SIZE ); // define SIZE as per your need
char *last = malloc( SIZE );
scanf("%s", first);
printf("%s", last); // FIXME : last is again not initialized
free( first ); first = NULL;
free( last ); last = NULL;
return 1;
}

Dealing with strings in C

I'm trying to write a stream editor in C and I'm having a hard time dealing with strings. After reading in the lines of a File, I want to store them locally in an array of Strings. However, when I try to store the variable temp into the array of strings StoredEdits I get a segmentation fault (core dumped) error. Furthermore, if I uncomment the char* temp2 variable and save this into my array as a workaround, then the last value read in gets stored for every value in the array.
I assume this has to do with the fact that temp2 is a pointer. I've tried a million things like malloc'ing and free'ing this variable after each iteration, but nothing seems to work.
Any help would be greatly appreciated.
#define MAX_SIZE 100
typedef char String[MAX_SIZE];
int main(int argc, char* argv[]){
char** StoredEdits;
int index, numOfEdits;
FILE *EditFile;
char* temp;
//char* temp2;
StoredEdits = (char**)malloc(MAX_INPUT_SIZE*sizeof(String));
/*Check to see that edit file is passed in.*/
if(argc < 2){
printf("ERROR: Edit File not given\n");
return(EXIT_FAILURE);
}
printf("%s\n",argv[1]);
if( (EditFile = fopen(argv[1],"r")) != NULL ){
printf("file opened\n");
numOfEdits = 0;
while(fgets(temp, MAX_STRING_SIZE, EditFile) != NULL){
printf("%d %s",numOfEdits,temp);
//temp2 = temp;
StoredEdits[numOfEdits++] = temp;
//StoredEdits[numOfEdits++] = temp;
printf("Stored successfully\n");
}
..........
printf("%d\n",numOfEdits);
for(index=0;index<numOfEdits;index++){
printf("%d %s\n",index, StoredEdits[index]);
}
You need to initialize temp to point to valid storage.
temp = malloc(MAX_STRING_SIZE+1);
It looks like you may have intended to do something like this:
String temp;
using your macro. This would be better as a regular char array. And the common name for this is buffer.
char buffer[MAX_STRING_SIZE+1];
Then, you should store in your array, not temp itself, but a new string containing a copy of the contents. There is a POSIX function strdup that should be helpful here. Note, strdup is not part of the C standard, but it is available in most hosted implementations. Historically, it comes from the BSD branch.
StoredEdits[numOfEdits++] = strdup(temp);
Let me backpedal a little and say that if you're allocating new storage for temp inside the loop, then you should skip the strdup because, as Jim Balter says, this will leak memory. If you allocate temp outside of the loop, then it makes little difference whether you allocate it statically (by declaring a char []) or dynamically (with malloc).
By the way, this line will not buy you much:
typedef char String[MAX_SIZE];
For why, see the classic Kernighan (the K in K&R) essay Why Pascal is not my favorite Programming Language.
Also note, that my examples above do not check the pointer returned by malloc. malloc can fail. When malloc fails it will return a NULL pointer. If you try to store data through this pointer, Kaboom!
You're right about your problem being because of pointer semantics. You should use copy the contents of the string from temp.
char *cpy = malloc(1 + strlen(temp));
if (cpy)
strcpy(cpy, temp);
//else handle error
StoredEdits[numOfEdits++] = cpy;
Others answered the reason for the error.
But from the program, i see that you tried to allocate a character double array. then you store each line read from the file into the array.
StoredEdits = (char**)malloc(MAX_INPUT_SIZE*sizeof(String));
if my assumption is right, then you should pass the array into strcpy like the below.
strcpy(StoredEdits[numOfEdits],tmp);
when you have a file where each line varies in size, it is better to go array of pointers points to character array.

Cause of seg fault in C

In my program I am getting a seg fault and I'm not sure the cause or how to find out the cause. Any help would be greatly appreciated!
In the code I am trying to read word by word, but I need to keep track of the line numbers. Then I am trying to create a linked list where the data is the word and line number.
(there are two files compiled together)
void main(int argc, char **argv){
file = fopen(argv[1],"r");
struct fileIndex *fIndex = NULL;
delimiters = " .,;:!-";/*strtok chars to seperate*/
int wCount = wordcount(file);/*number of words in file*/
char **str[wCount+1];/*where the lines are being stored*/
int j=0;
while(!feof(file)){/*inserting lines*/
fscanf(file, "%s", &str[j]);
j++;
}
char *token, *cp;
int i;
int len;
for(i = 0; str[i]; i++){/*checking to insert words*/
len = strlen(*str[i]);
cp = xerox(*str[i]);
token = strtok(cp, delimiters);
if(!present(fIndex, token)){
insert(fIndex, i+1,token);
}
while(token!=NULL){
token = strtok(NULL, delimiters);
if(!present(fIndex, token)){
insert(fIndex, i+1,token);
}
}
i++;
}
fclose(file);
}
int strcmpigncase(char *s1, char *s2){/*checks words*/
for(;*s1==*s2;s1++,s2++){
if(*s1=='\0')
return 0;
}
return tolower(*s2)-tolower(*s2);
}
present(struct fileIndex* fIndex, char *findIt){/*finds if word is in structure*/
struct fileIndex* current = fIndex;
while(current!=NULL){
current = current -> next;
if(strcmpigncase(current -> str, findIt)==0){
return current -> lineNum;
}
}
return 0;
}
void insert(struct fileIndex *head, int num, char *insert){/*inserts word into structure*/
struct fileIndex* node = malloc(sizeof(struct fileIndex));
node -> str = insert;
node -> lineNum = num;
node -> next = head;
head = node;
}
#define IN_WORD 1
#define OUT_WORD 0
int wordcount(FILE *input)/*number of words in file*/
{
FILE *open = input;
int cur; /* current character */
int lc=0; /* line count */
int state=OUT_WORD;
while ((cur=fgetc(open))!=EOF) {
if (cur=='\n')
lc++;
if (!isspace(cur) && state == OUT_WORD) {
state=IN_WORD;
}
else if (state==IN_WORD && isspace(cur)) {
state=OUT_WORD;
}
}
return lc;
}
char *xerox(char *s){
int i = strlen(s);
char *buffer = (char *)(malloc(i+1));
if(buffer == NULL)
return NULL;
char *t = buffer;
while(*s!='\0'){
*t=*s;
s++; t++;
}
*t = '\0';
return buffer;
}
This code has a fairly high rate of problems. I'll dissect just the first few lines to give an idea:
void main(int argc, char **argv){
main should return int, not void. Probably not causing your problem, but not right either.
file = fopen(argv[1],"r");
You really need to check the value of argc before trying to use argv[1]. Invoking the program without an argument may well lead to a problem. Depending on how you've invoked it, this could be the cause of your problem.
struct fileIndex *fIndex = NULL;
Unless you've included some headers you haven't shown, this shouldn't compile -- struct fileIndex doesn't seem to have been defined (nor does it seem to be defined anywhere I can see in the code you'e posted).
delimiters = " .,;:!-";/*strtok chars to seperate*/
int wCount = wordcount(file);/*number of words in file*/
This (wordcount) reads to the end of the file, but does not rewind the file afterward.
char **str[wCount+1];/*where the lines are being stored*/
From your description, you don't really have any need to store lines (plural) at all. What you probably want is to read one line, then tokenize it and insert the individual tokens (along with the line number) into your index, then read the next line. From what you've said, however, there's no real reason to store more than one raw line at a time though.
int j=0;
while(!feof(file)){/*inserting lines*/
As noted above, you've previously read to the end of the file, and never rewound the file. Therefore, nothing inside this loop should ever execute, because as soon as you get here, feof(file) should return true. When/if you take care of that, this loop won't work correctly -- in fact, a loop of the form while (!feof(file)) is essentially always wrong. Under the circumstances, you want to check the result of your fscanf, with something like:
while (1 == fscanf(file, "%1023s", line))
...so you exit the loop when attempting to read fails.
fscanf(file, "%s", &str[j]);
What you have here is basically equivalent to the notorious gets -- you've done nothing to limit the input to the size of the buffer. As shown above, you normally want to use %[some_number]s, where some_number is one smaller than the size of the buffer you're using (though, of course, to do that you do need a buffer, which you don't have either).
You've also done nothing to limit the number of lines to the amount of space you've allocated (but, as with the individual lines, you haven't allocated any). I almost hesitate to mention this, however, because (as mentioned above) from your description you don't seem to have any reason to store more than one line anyway.
Your code also leaks all the memory it allocates -- you have calls to malloc, but not a single call to free anywhere.
Actually, some of the advice above is (at last more or less) wrong. It's looking at how to fix an individual line of code, but in reality you probably want to structure the code a bit differently in general. Rather than read the file twice, once to count the words, then read it again to index the words, you probably want to read a line at a time (probably with fgets, then break the line into words, and count each word as you insert it into your index. Oh, and you almost certainly do not want to use a linked-list for your index either. A tree or a hash-table would make a great deal more sense for the job.
I also disagree with the suggestion(s) in the direction of using a debugger on this code. A debugger is not likely to lead toward significantly better code -- it may help you find a few of the localized problems, but is unlikely to lead toward a significantly better program. Instead, I'd suggest a pencil and a piece of paper as the tools you really need to use. I believe your current problems stem primarily for not having thought about the problem enough to really understand what steps are needed to accomplish the goal, and a debugger isn't likely to help much in finding an answer to that question.
If you don't have a good debugger handy, a good fallback is to simply add a few printf statements at steps through the code, so you can see how far it gets before crashing.
In this code:
char **str[wCount+1];/*where the lines are being stored*/
int j=0;
while(!feof(file)){/*inserting lines*/
fscanf(file, "%s", &str[j]);
j++;
}
str is an array of pointers to char *s. In your loop you are reading each piece of input into a slot in it. There are a couple of problems.
I think there's a miscount in the number of *s vs. &s (I don't usually program with that many levels of pointer indirection to avoid having to think so hard about them ;-). &str[j] is the address of that array element, but that array element is a pointer to a pointer; now you have a pointer to a pointer to a pointer. If you had instead char *str[wCount+1], and read into str[j], I think it might match up. (Also I don't use fscanf much, so perhaps someone can confirm how best to use it.)
More obviously, you're not actually allocating any memory for the string data. You're only allocating it for the array itself. You probably want to allocate a fixed amount for each one (you can do that in the loop before each fscanf call). Remember that you're fscanf could in practice read more than that fixed size, resulting in another memory error. Again, working around that requires an expert in fscanf usage.
Hope this helps for a start. If the printf suggestion finds a more specific point in the code where it fails, add that to the question.

Resources