Thread: Problem with RPC and scanf

  1. #1
    Registered User
    Join Date
    Jan 2007
    Posts
    7

    Problem with RPC and scanf

    Hi all,

    I know scanf can generate some input errors, and gets should be avoided at all cost, so I wonder if someone can sugest a work around for a problem I have.
    I'm using rcpgen to generate client and server stubs for a remote call procedure project I'm doing in school, everything is working fine, except for some times when i use scanf for getting input from keyboard, i know the problem is there because if i use argv[] to get that input from command line, or initialize the variables with some values, everything works fine.

    The code main():
    Code:
    main(argc,argv)
    int argc; char *argv[];
    { 
    	 
    	namelist nl;
    	char *server;
    	char operacao;
    
    	if (argc!=2)
    	{
    		fprintf(stderr,"Sintaxe correcta: %s <host>\n",argv[0]);
    		exit(1);
    	}
    
    	server = argv[1]; 
    	
    	/* -------------------- MENU PRINCIPAL ---------------------- */
    	printf("\n\n\n******************************************************\n");
    	printf("*                  MENU PRINCIPAL                    *\n");
    	printf("*                                                    *\n");
    	printf("*    a) Listar directorio do servidor    =  DIR      *\n");
    	printf("*    b) Mudar directorio do servidor     =  CD       *\n");
    	printf("*    c) Mudar directorio do servidor     =  PWD      *\n");
    	printf("*    d) Copiar Ficheiro do servidor      =  GET      *\n");
    	printf("*    e) Copiar Ficheiro para o servidor  =  PUT      *\n");
    	printf("*                                                    *\n");
    	printf("******************************************************\n\n");
    	
    	printf("Opcao: ");
    	scanf ("%c",&operacao);
    
    	switch (operacao)
    	{
    		case 'a':
    		case 'A':
    			listaDirectorio((novaLigacao(server)),server, nl);
    			break;
    		case 'b':
    		case 'B':
    			defineDIR(server);		
    			break;
    		case 'c':
    		case 'C':
    			mostraDIR(server);		
    			break;
    		default:
    			printf("\nA opcao introduzida nao e valida\n");
    	}
    	
    }
    when selection 'b' option i use a function similiar to a CD linux command (change directory on server)

    Code:
    /* LIKE 'CD' CHANGES DIR ON SERVER */
    defineDIR(char *server)
    {	
        CLIENT *clnt;
        int *result;
        char *dir;
    	
        printf("\nDirectory: ");
        scanf("%s",dir);
    	
        /* Calls novaLigacao function that creates a new connection to server */
        clnt = novaLigacao(server);
    
        /* set's the dir on the server */	
        result = fixadir_1(&dir, clnt);
        if (result == NULL) 
       {
    	clnt_perror(clnt, server);
    	exit(1);
        }	
        /* cleaning */
        clnt_destroy(clnt);
        exit(0);	
    }
    if I initialize the char *dir with for example "/root" like the code below, my code works fine, and the server get his dir defined as "/root" so the problem must be on scanf function and getting the input from the keyboard, also before you say it, the fflush(stdin) doesn't changes anything.

    This way it works:

    Code:
    /* LIKE 'CD' CHANGES DIR ON SERVER */
    defineDIR(char *server)
    {	
        CLIENT *clnt;
        int *result;
        char *dir="/root";
    	
        /* Calls novaLigacao function that creates a new connection to server */
        clnt = novaLigacao(server);
    
        /* set's the dir on the server */	
        result = fixadir_1(&dir, clnt);
        if (result == NULL) 
       {
    	clnt_perror(clnt, server);
    	exit(1);
        }	
        /* cleaning */
        clnt_destroy(clnt);
        exit(0);	
    }
    The error i get is like this: "segmentation fault"
    Help this newb please.

    Thanks for your time.

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Code:
    char *dir;
    	
    printf("\nDirectory: ");
    scanf("%s",dir);
    The variable dir does not have any space allocated to it. When you scanf to it, you are writing data to random memory locations. You need to allocate some memory for it first before you start writing to it.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > before you say it, the fflush(stdin) doesn't changes anything.
    That's because it's the wrong thing to do anyway - it's action is undefined - see the FAQ.

    > main(argc,argv)
    > int argc; char *argv[];
    This 'K&R' style of C declaration was made obsolete in 1989 - why are you still using it?

    > char *dir;
    > scanf("%s",dir);
    This is the real problem, you haven't allocated any space for the input string.

    Try using say
    char dir[100];

    Also, read the FAQ on how to use say fgets() and sscanf() to read a line of input, then validate and convert that input to whatever form you need.


    > This way it works:
    > char *dir="/root";
    But only by luck. On some systems, "strings" are in read-only memory, so you'd still get a segmentation fault as soon as your scanf tried to modify it. Use an array as shown.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Jan 2007
    Posts
    7
    1st of all thank you all for your reply's, I did also try to allocate memory by doing char dir[256]; and it didn't work, i'll try to use the fgets();

    Salem I usualy use "main(int argc, char *argv)" but as i only use C for education purposes on school I saw a example with this declaration on main and thought it was funny and used it to see the result :-), I actually forgot to change it back.

    PS- I'm taking a good look at the FAQ's now, I only read 1 C book till now, and really need to improve my knowledge.

  5. #5
    Registered User
    Join Date
    Jan 2007
    Posts
    7
    One more thing by declaring char dir[128]; for example i cannot pass the 1st argument of function
    Code:
    result = fixadir_1(&dir, clnt);
    like "&dir" how is the correct way of passing "dir" as a argument to "fixadir_1" ??

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    I dunno - what is the prototype for fixadir_1() ?

    If it's just a char * for parameter 1, then
    result = fixadir_1(dir, clnt);
    would be fine.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Jan 2007
    Posts
    7
    ok I resolve the problem with malloc() function like this
    Code:
    /* LIKE 'CD' CHANGES DIR ON SERVER */
    defineDIR(char *server)
    {	
        CLIENT *clnt;
        int *result;
        char *dir;
    
        printf("\nPlease choose new dir to set on server: ");
        dir=malloc(100);
        scanf("%s", dir);
    	
        /* Calls novaLigacao function that creates a new connection to server */
        clnt = novaLigacao(server);
    
        /* set's the dir on the server */	
        result = fixadir_1(&dir, clnt);
        if (result == NULL) 
       {
    	clnt_perror(clnt, server);
    	exit(1);
        }	
        /* cleaning */
        clnt_destroy(clnt);
        exit(0);	
    }
    using fgets() didn't work, passed right to the end without prompting for any input, weird...

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    The reason fgets "didn't work", was because you were using scanf some place before it, leaving your newline in the input stream. You shouldn't mix input methods.


    Quzah.
    Hope is the first step on the road to disappointment.

  9. #9
    Registered User
    Join Date
    Jan 2007
    Posts
    7
    Quote Originally Posted by quzah
    The reason fgets "didn't work", was because you were using scanf some place before it, leaving your newline in the input stream. You shouldn't mix input methods.


    Quzah.
    if you mean outside the function defineDir() yes i was using scanf, but inside defineDir() i removed all scanf()...

  10. #10
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    It doesn't matter. Say you type in "hello world", and press enter. You do that in one function, but that function only reads "hello world" and not the newline. Now you're in a new function, and you call fgets, which stops checking for input when it reaches a newline. You still have a newline waiting in your input stream, so when you call fgets, the first thing it reads is the newline, at which point it stops looking for input.


    Quzah.
    Hope is the first step on the road to disappointment.

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > ok I resolve the problem with malloc() function like this
    Don't forget to call free as well.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  12. #12
    Registered User
    Join Date
    Jan 2007
    Posts
    7
    Quote Originally Posted by Salem
    > ok I resolve the problem with malloc() function like this
    Don't forget to call free as well.
    Thanks, i analized the malloc() function again, didn't notice that free was also a must to free memory allocated, i was in a rush to get this done :-)

    Also thanks quzah, i thougt scanf() was dicarding the \n, now it makes sense why fgets() didn't make nothing, it did actually, it read the \n from the io, damm it's bad to be such a noob, ohh well there's always room for improvement i guess.

Popular pages Recent additions subscribe to a feed