ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
considering the following three file, I use
gcc -c main.c
g++ -c reciprocal.cpp
to compile them, and
g++ -o main.out main.c reciprocal.cpp
to link them, and when I run 'main' with
./main.out
the shell display the following error code:
segmentation fault.
Code:
/*main.c*/
#include <stdio.h>
#include <stdlib.h>
#include "reciprocal.hpp"
int main (int argc, char **argv)
{
int i;
i = atoi (argv[1]);
printf ("The reciprocal of %d is %g\n", i, reciprocal (i));
return 0;
}
/*reciprocal.cpp*/
#include <cassert>
#include "reciprocal.hpp"
double reciprocal (int i) {
// I should be non-zero.
assert (i != 0);
return 1.0/i;
}
/*reciprocal.hpp*/
#ifdef __cplusplus
extern "C" {
#endif
extern double reciprocal (int i);
#ifdef __cplusplus
}
#endif
the code is from the book "Advanced Linux programming"
on running the following file, it also display the segmentation fault error message. But when I run it on Windows xp, it has no error.It is a simple scanner program made by me.
Code:
/*Exp-1 Scanner of C*/
#include<stdio.h>
#include<ctype.h>
#include<string.h>
/*#include<conio.h>*/
#include<stdlib.h>
#define N 20
void scan(FILE *);
int isKeyword(char *);
int isDirective=0;
main(){
char *fileName="";
FILE *fPtr;
printf("Please enter the file name of the C program for scanning: ");
scanf("%s",fileName);
if((fPtr = fopen(fileName, "r")) == NULL){
printf("File could not be opened\n");
/*getch();*/
exit(1);
}
scan(fPtr);
return;
}
void scan(FILE *fPtr){
char *token="", *symbol="", *attr="", ch, s[2];
while(!feof(fPtr)){
*token='\x0';
ch=fgetc(fPtr);
if(ch=='\n')
isDirective=0;
while(isspace(ch))
ch=fgetc(fPtr);
if(isdigit(ch)){
while(isdigit(ch)){
s[0]=ch; s[1]='\0';
strcat(token,s);
ch=fgetc(fPtr);
}
if(isDirective==0){
symbol="Number";
attr=token;
}
else{
symbol="Number in directive";
attr=token;
}
fseek(fPtr,-1L, SEEK_CUR); /*input pointer back a character*/
}
else if(isalpha(ch)){
while(isalnum(ch)){
s[0]=ch; s[1]='\0';
strcat(token,s);
ch=fgetc(fPtr);
}
fseek(fPtr,-1L,SEEK_CUR);
if(isKeyword(token))
symbol="Keyword";
else if(isDirective==0)
symbol="Identifier";
else
symbol="ID in directive";
attr=token;
}
else switch(ch){
case '/':
if(fgetc(fPtr)=='/'){
ch=fgetc(fPtr);
while(ch!='\n'){
s[0]=ch; s[1]='\0';
strcat(token,s);
ch=fgetc(fPtr);
}
fseek(fPtr,-1L,SEEK_CUR);
symbol="Single line comment";
attr=token;
}
if(fgetc(fPtr)=='*'){
ch=fgetc(fPtr);
L1: while(ch!='*'){
s[0]=ch; s[1]='\0';
strcat(token,s);
ch=fgetc(fPtr);
}
if(ch=='/'){
symbol="Multiple line comment";
attr=token;
}
else
goto L1;
}
break;
/*case '#':
isDirective=1;
while(isalpha(ch)){
s[0]=ch; s[1]='\0';
strcat(token,s);
ch=fgetc(fPtr);
}
fseek(fPtr,-1L,SEEK_CUR);
symbol="directive";
attr=token;
break;*/
case '=':
if(fgetc(fPtr)=='='){
symbol="Relational-Operator";
attr="EQ";
}
else{
fseek(fPtr,-1L,SEEK_CUR);
symbol="Assign-Operator";
attr="=";
}
break;
case ';':
symbol="End-of-statement";
attr=";";
break;
case ':':
symbol="Label";
attr=":";
break;
case '<':
if(isDirective==1){
symbol="Directive-left";
attr="<";
}
else if(fgetc(fPtr)=='='){
symbol="Relational-Operator";
attr="LE";
}
else{
fseek(fPtr,-1L,SEEK_CUR);
symbol="Relational-Operator";
attr="LT";
}
break;
case '>':
if(isDirective==1){
symbol="Directive-right";
attr=">";
}
else if(fgetc(fPtr)=='='){
symbol="Relational-Operator";
attr="GE";
}
else{
fseek(fPtr,-1L,SEEK_CUR);
symbol="Relational-Operator";
attr="GT";
}
break;
case '!':
if(fgetc(fPtr)=='='){
symbol="Relational-Operator";
attr="NE";
}
else{
fseek(fPtr,-1L,SEEK_CUR);
symbol="Logical-Operator";
attr="NOT";
}
break;
case '{':
symbol="Block-begin";
attr="{";
break;
case '}':
symbol="Block-end";
attr="}";
break;
default:
s[0]=ch; s[1]='\0';
symbol="Other";
attr=s;
break;
}
printf("Symbol: %s\t\tAttr: %s\n",symbol,attr);
/*getch();*/
}
}
int isKeyword(char *token){
char *key="void int char float double long unsigned if else switch case do while break continue return union typedef const default enum goto short sizeof static struct";
if(strstr(key,token) != NULL)
return 1;
else
return 0;
because when you supply no parameters to your ./main.out it will call atoi(0) and that causes segmentation fault. You should replace it with
Code:
if (argv[1]) i = atoi(argv[1]);
else i = 0; // or something else
The second program have more errors. You should read more about how to work with strings (or with char*) in C/C++.
e.g., when you do
Code:
char *variable;
variable = "constant string"
you didn't copied string to your variable, but you only made your variable to point to that string and because it's constant string you can't do *variable='x' (as you do in your scan() function).
And secondly you call scanf("%s",fileName); but you need firstly to allocate space for it or declare it as char fileName[400] or similar.
int main (int argc, char **argv)
{
int i;
i = atoi (argv[1]);
printf ("The reciprocal of %d is %g\n", i, reciprocal (i));
return 0;
}
because you get element 1 of the argv array, while this array only contains one element (the program's name) when the program is started without arguments. To check if this is the case, try this:
Code:
int main (int argc, char **argv)
{
int i;
if(argc < 2)
{
printf("You didn't provide an argument\n");
return 1;
}
i = atoi (argv[1]);
printf ("The reciprocal of %d is %g\n", i, reciprocal (i));
return 0;
}
One thing I see is that you're allocating 100 bytes of memory and saving the pointer to it to the attr variable. But then later you're doing things like attr=token and attr=")". This effectively loses that 100 bytes of memory you allocated and creates a memory leak. It's impossible to free() that memory one you lose the pointer to it.
EDIT - You're doing the same thing with the symbol variable.
Originally posted by itsme86 One thing I see is that you're allocating 100 bytes of memory and saving the pointer to it to the attr variable. But then later you're doing things like attr=token and attr=")". This effectively loses that 100 bytes of memory you allocated and creates a memory leak. It's impossible to free() that memory one you lose the pointer to it.
EDIT - You're doing the same thing with the symbol variable.
How to solve the problem you've pointed?
How to assign pointer attr and symbol to another string value, which don't cause memory or other problem?
you don't need to do symbol=malloc(100); because you assign to this variable only constant string without further
appending or changing characters in it. You can even delete attr=malloc(100); and it will work, but I don't recommend it
for further developing of your program. Maybe this helps you understand how to work with strings:
char *c, *d, *e;
c="Hello"; // OK
// c[0]='S'; // error -> c points to constant string and can't be changed
// free(c); // error -> you can't free constant string
c=(char*)malloc(20); //OK -> you allocated 20bytes; let say it's at memory address A
// c="Hello"; // not OK, because you've lost pointer to memory address A and can't free() (dealocate) this memory
c[0]='C'; c[1]='\0'; //OK;
// c[20]='\0'; // error -> 20 is out of range
d=c; // OK; variables d,c points to the same memory address (A)
d[0]='S'; // OK; now c[0]=='S'
// for copying string to another string use function strcpy(char *dest, const char *src)
// but remember that dest must be allocated to at least 1+strlen(src) bytes
d="Hm";
// strcpy(d, c); // error
d=(char*) malloc(20); // let say we allocated memory at address B
strcpy(d, c); // OK, string "S" copied to address B
d==c; // false; they point to different adresses
strcmp(d, c); // returns 0 -> strings are equal
e=d;
free(e); // OK; deallocated B
free(c); // OK; deallocated A
// free(d); // error; already deallocated
And there are also some different rules in declaration:
char *a="Th"; is equal to char *a; a="Th";
char a[7]="Th"; is equal to char a[7]; a[0]='T'; a[1]='h'; a[2]='\0';
So back to your program - with your variable attr you always do attr=token; or attr="const. string";
You can do this without attr=malloc(100); but remember that in the first case if you later change string pointed to by
variable token that this will also change string pointed to by variable attr (because attr==token).
Therefore you should malloc it and instead of attr=token; use strcpy(attr, token); (and then, of course, also instead
of attr="const. string"; use strcpy(attr, "const. string"); to be able to free(attr) at the end of your scan() function).
And last thing, you don't need isHex(char) because there's isxdigit(char) in ctype.h
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.