int main(int argc, char *argv[]){
struct protoent *proto;
char **p_aliases;
if(argv[1]==NULL){
char name[25];
printf(" give a valide protocol name\n");
scanf("%s",name);
proto = getprotobyname(name);
}
else{
proto = getprotobyname(argv[1]);
}
if(argv[1]==NULL){
printf("%s the protocol name is :\n",proto->p_name);
printf("%s the protocol alias is\n",proto->p_aliases);
printf("%d the protocol number is \n",proto->p_proto);
return 0;
}
}
// i'm not getting the proper output, just a fragmentation fault
Problems with this code:
argvc < 2 would be more robust than argv[1] == NULL, though that's probably not the issue here.
There's nothing to prevent scanf reading more than the 25 characters you've allocated.
The second if will mean there is no output at all if argv[1] is non-null.
getprotobyname returns a null-pointer when the name is not recognised, but you don't check.
You try to print proto->p_aliases, but that has type char **, so you probably need to print proto->p_aliases[0] (and should probably check that is non-null).
Anyway, besides all that, when you get a seg fault it's better to run the code under an debugger before you go ask other people to do your work for you. The debugger will probably tell you exactly where the problem is, and if it doesn't you can step through the code and narrow it down very easily.
Related
I've defined a struct and a function that returns a pointer to that struct and whenever I try to invoke it I get a runtime error says ** error: conflicting types for ‘readVirus’**
typedef struct virus {
unsigned short SigSize;
char virusName[16];
unsigned char* sig;
}virus;
virus* readVirus(FILE* file){
virus *res;
res=(virus*)malloc(sizeof(virus));
fread(&res->SigSize,2,1,file);
fread(&res->virusName,16,1,file);
res->sig=(char*)malloc(res->SigSize);
fread(res->sig,res->SigSize,1,file);
return res;
free(res);
}
int main(int argc, char **argv) {
FILE *input;
input = fopen(argv[1],"rb");
virus *res;
res=(virus*)malloc(sizeof(virus));
res=readVirus(input);
printf("%s",res->virusName);
free(res);
fclose(input);
}
I've tried to copy the body of readVirus into main directly and deleted the function and it worked perfectly, so I don't think that its an function implementation issue.
thanks in advance :)
having
typedef struct virus {
unsigned short SigSize;
char virusName[16];
unsigned char* sig;}
struct virus* readVirus(FILE* file){
first a ';' is missing after the '}' of the struct and you do not define the type virus, so you need to use struct virus every where in your code
But probably you wanted wanted :
typedef struct virus {
unsigned short SigSize;
char virusName[16];
unsigned char* sig;
} virus;
to allow to just write virus without the struct after its definition
I encourage you to use an uppercase character to start the name of your types, so Virus rather than virus, that help the reading of the code making a distinction with the name of the variables for instance
Problems in main
I get a runtime error says ** error: conflicting types for ‘readVirus’**
This is a message produced when you compile your program, not when you execute it and this is because in that line :
res->sig=(char*)malloc(res->SigSize);
res is a pointer to a virus but your cast is (char*), the types are not the same.
You can fix the cast to use (virus*) but in fact you can just remove it.
Doing :
res=malloc(sizeof(virus));
res=readVirus(input);
the first assignment is lost, introducing a memory leak, remove the fiest assignment
Note in main you do not free res too, at the end of the program this is not a problem, except if you want to check the memory usage with a tool like valgrind
You use argv[1] without checking before the program received an argument, I encourage you do do something like that at the beginning of your program :
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <file>\n", *argv);
return -1;
}
else {
I encourage you to check the result of fopen to check you was able to open the file and to signal when it is not the case. If you have the function strerror use it, for instance :
if (input == NULL) {
fprintf(stderr, "cannot open %s : ", argv[1], strerror(errno));
return -1;
}
Flush your printing with a final newline, and you just want to print a string, so in main replace
printf("%s",res->virusName);
by
puts(res->virusName);
Problems in readVirus
In
fread(&res->SigSize,2,1,file);
fread(&res->virusName,16,1,file);
do not use literal number for the size, use sizeof to get the right size whatever happens :
fread(&res->SigSize, sizeof(res->SigSize), 1, file);
fread(&res->virusName, sizeof(res->virusNamee), 1, file);
I also recommend you to check your reads success and to signal when there is an error
Are you sure the file is a binary file where sigSize is the binary representation ? I mean for the size 1234 the file contains the byte of code 4 then the byte of code 210 or the reverse
I have this recursive function which creates all possible strings from a dictionary and encrypt them so that they can be compared with some saved hashes.
Earlier, I had some predefined value for the max length of passwords but I tried to change it with argv[1].
But when I execute my program, I get a Segmentation Fault with not explanation.
By the way, all the includes are present as they should but I didn't put them in the post since it is somewhat bugged.
int recur(char * mot , char * tab,int l,int max_l)
{
// Because this was an exercice we had to do in class , i deleted this part
// so some of my classmates dont copy/paste my code
// if you are interested , contact me
int main(int argc, char *argv[])
{
char letters[36] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9'};
char s[10]="";
s[9]='\0';
int l=0;
int max_l;
sscanf (argv[1],"%d",&max_l);
printf("max_l : %i\n",max_l);
printf("Debut ! \n");
recur(s,letters,l,max_l);
}
Thanks for your time!
printf("Argv[1] : %s\n", max_l);
This is undefined behavior. You are giving wrong format specifier. That's why you get seg fault you are trying to print an int using %s format specifer. It looks for the \0 and then it doesn't. So it accesses some memory which it shouldn't resulting in UB. (And that resulted in segmentation error).
It should be
printf("Argv[1] : %d\n", max_l);
Also another major problem is not every control flow of this recursive function returns int. This is a pathway to bigger problem. In case the there is no return value when one is expected the behavior will be undefined.
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.
I wrote this little program to practice arrays, which is supposed to take in a max of 10 characters, and the ending \0. It works, but it works too well, and even if I put in a 50 character name, it spits out the correct input. What gives?
#include <stdio.h>
int main(int argc, char const *argv[])
{
char name[11];
printf("Enter your name: ");
scanf("%s", name);
printf("Hi, %s\n", name);
return 0;
}
You are overwriting past the end of the array that you allocated - you need to specify as part of the scanf the length of the string to be read to make sure that it fits.
scanf("%10s", name);
An improvement to your code would be to generate the format string so that it always has the right size.
#include <stdio.h>
int main(int argc, char const *argv[])
{
char name[11];
char formatstr[50];
snprintf(formatstr, sizeof(formatstr), "%%%ds", sizeof(name)-1);
printf("Enter your name: ");
scanf(formatstr, name);
printf("Hi, %s\n", name);
return 0;
}
When you allocate an array in C you are just getting the starting memory address of a block of memory guaranteed to be free for you to use, nothing more. This guarantee is based in the assumption that you are not going to use this array to read/write any memory location outside of its boundaries, which you just did!
Higher level languages, such as Java or C#, will throw an exception (an error) when you try to access a memory location outside of your array boundaries, unfortunately in C you are on your own.
Even though you example seems harmless, this kind of access violation is a common bug in software development and can lead from simple malfunctioning to an accidental stack-overflow!
I'm trying to write a program that reads in entries from a file into a dynamically allocated array of structures using input redirection. My program compiles fine but I'm getting a segmentation fault and I'm having trouble finding the cause.
Here's my Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct StudentData
{
char* name;
char* major;
double gpa;
} Student;
int main()
{
Student* data = (Student*)malloc(sizeof(Student)*5);
int i;
for(i = 0; i < 5; i++)
{
// allocate memory for name and read input
data[i].name = malloc(50);
*(data+i)->name == scanf("%s", (char*)&data[i].name);
// allocate memory for major and read input
data[i].major = malloc(30);
*(data+i)->major == scanf("%s", (char*)&data[i].major);
// read input for gpa
(data+i)->gpa == scanf("%lf", &data[i].gpa);
//print array
printf("%s\n%s\n%f\n", data[i].name, data[i].major, data[i].gpa);
}
}
Any clues? If it seems obvious it's because I'm relatively new to C!
This line:
*(data+i)->name == scanf("%s", (char*)&data[i].name);
Ignoring the weird and void == for a moment, &data[i].name is wrong since you're taking an address of a pointer. data[i].name would be sufficient here, since the name field is already an address scanf can write into.
And the cast to (char*) is what probably shuts the compiler up about it - did you enter it for this purpose :-) ? Because &data[i].name has the type char**, which scanf wouldn't accept, unless you forcefully casted it to char*.
As a general advice, try to avoid scanf - it leads to very unsafe code (as you've just seen!) Instead, use fgets to read a line (from the standard input too) and then break this line into its constituents. This may initially take a bit more code to implement, but leads to much safer and more predictable code.
*(data+i)->name == scanf("%s", (char*)&data[i].name);
What are you comparing the return value of scanf for? Just remove the first part. Also, data[i].name is already a pointer, so you shouldn't take the address once again. It should just be:
scanf("%s", data[i].name); // no & because name is already a pointer
And similarly:
scanf("%s", data[i].major);
scanf("%lf", &data[i].gpa); // & here because gpa is just a double
There is some unnecessary code being used with scanf, like *(data+i)->name ==. That doesn't do anything useful (and is probably causing the segfault). If it weren't causing access errors, it would compare the return value of scanf with the pointer and then ignore the result of the comparison. (A decent compiler would have warned about this.)
After getting rid of the excess code, it will be technically okay, except there is nothing to prevent buffer overrun. That's done either by controlling the input data, or adding limits to the lengths of the strings, like with scanf("%50s", data[i].name);
&data[i].name and &data[i].major are of type char **, so you cannot safely cast it to char *.
Losing the ampersand will correct your error.
There are also other logical errors with the use of scanf(), but that's probably overwhelming - it'd be nice if you revisited this code once you entered a name of more than 50 characters.