Thread: Pointer to pointer assignment? PLEASE HELP!!!

  1. #1
    Registered User Ryan.'s Avatar
    Join Date
    Jul 2010
    Location
    Berkeley, CA
    Posts
    16

    Pointer to pointer assignment? PLEASE HELP!!!

    I am. Going. Freaking. Crazy. I searched all over for a solution, and cannot find one. Please don't harp on me if you can find one in like 30 seconds -- maybe I suck at search.

    This is, plain and simply, what I want to do:

    Mutate argv's elements (having been passed "char** argv") IN PLACE (no change of address)

    I have an array of strings called saved_args (char** saved_args)

    So, like,

    saved_args[0] = "PUT IN ARGV[0]"
    saved_args[1] = "PUT IN ARGV[1]"

    argv[0] = "REPLACE"
    argv[1] = "ME"

    I tried using strcpy and kept getting segfault. I think I have the idea right (I have to COPY the string into the location), but I cannot figure out the syntax to do it.

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Just use saved_args instead of argv because:

    - If you change an argument to something longer than what argv can store;
    - If you change argv and some other part of the program needs the original arguments;
    - If you need certain arguments to be effective even when they aren't passed by the user;

    argv, and by extension your program, will be fubar.

  3. #3
    Registered User Ryan.'s Avatar
    Join Date
    Jul 2010
    Location
    Berkeley, CA
    Posts
    16
    There are problems with that.

    For one, saved_args doesn't contain everything argv does -- it is not a 1:1 map

    Secondly, the program package uses argv, so I have to change that directly (or somehow change what it points to, but I don't know if that will work.)

    Here's the jist of it:

    > alias c 'cast blizzard'
    > alias
    There is 1 alias:
    c = 'cast blizzard'

    > c golem

    Code:
    argv = {c, golem}
    argv NEEDS TO BE {cast, blizzard, golem}
    Again, the entire package uses argv (which is originally the user's input)

  4. #4
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Do not try and modify argv. You should really treat it as if it were defined as:
    Code:
    const char * const * argv
    Just copy the data to a new location and modify it as much as you like there.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  5. #5
    Registered User Ryan.'s Avatar
    Join Date
    Jul 2010
    Location
    Berkeley, CA
    Posts
    16
    Everything in the package is linked to argv... the assignment specifically requires us to modify argv.

  6. #6
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Modifying the strings passed to your program is legal, but you can't modify them to be longer than they already are. If your assignment requires that, it is broken by design. It's entirely possible your instructor uses an implementation that “works” when the new strings are longer and simply assumes that because it works for him, it is legal. Now your assignment becomes figuring out how to deal with an instructor who doesn't have a full grasp of the language. That's probably harder than the original assignment!

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > alias c 'cast blizzard'
    > alias
    Is this your real shell, or something you've done?

    Because in regular bash, there is no problem to be solved.
    Code:
    $ cat foo.c
    #include <stdio.h>
    int main ( int argc, char *argv[] ) {
        int i;
        for ( i = 0 ; i < argc ; i++ )
            printf("%d:%s\n", i, argv[i] );
        return 0;
    }
    $ gcc -o cast foo.c
    $ alias c='./cast blizzard'
    $ c golem
    0:./cast
    1:blizzard
    2:golem
    The alias is expanded before the program is run, and the program gets the fully expanded command line.


    Whilst you can easily do things like
    argv[1] = "another string";

    What you're not going to be able to do is make the existing argv[] longer (say be able to insert "blizzard")
    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.

  8. #8
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    I'm kind of struggling to get this right. So are you trying to get the command line arguments to the saved_args or the other way around. As argv is most commonly used for getting the command line argument. So doing the other way around like placing the values from saved_args to argv?

    Have you got any code which you've written so far? Could you show us where exactly the problem you’re facing?

    ssharish
    Life is like riding a bicycle. To keep your balance you must keep moving - Einstein

  9. #9
    Registered User Ryan.'s Avatar
    Join Date
    Jul 2010
    Location
    Berkeley, CA
    Posts
    16
    I did not understand correctly how main handled the function. When I finally understood (this morning), it took me 1 hour to code it and get it working. I have spent over 20 hours on it approaching it completely wrong. I feel like jumping off a f$%king bridge right now.

    EDIT: Thanks for the help anyway... and sorry for wasting your time.
    Last edited by Ryan.; 07-03-2010 at 01:21 PM.

  10. #10
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    Dude, it won't be the last time it happens...trust me. Don't get discouraged.

  11. #11
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    It's never a waste of time if you were helped in the end.

    P.S. Don't forget your bungee cord!
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  12. #12
    Registered User Ryan.'s Avatar
    Join Date
    Jul 2010
    Location
    Berkeley, CA
    Posts
    16
    I thought I fixed it, but apparently not.

    I have it 90% working, but I still have the issue with main's args that need to change.

    Instead of being vague, this time I am going to be very specific because this project is due before midnight tonight.

    This is the relevant code FROM main:
    Code:
    int main(int argc, char **argv) {
    
    /* ... ... ...*/
    
            char buf[256];
    	char buf2[256];
            char *words[32];
            int num_words;
    /* ... */
            char *command_name = words[0];
    /* ... */
            cmd_fxn_t cmd_to_do = lookup_c(command_name, &num_words, words, buf2);
    /* ... */
    	command_name = words[0];
    	
    	if(cmd_to_do != NULL) {
    	    // and do it
    	    int elapsed_time = cmd_to_do(num_words, words);
    	    tick_world(elapsed_time, is_player_vulnerable(command_name));
    	}
    words MUST be changed in that call for the int elapsed_time and tick_world to work.

    However, I haven't figured out how to change num_words in lookup_c.

    Here is ALL the code from lookup_command, which is in a different file:

    Code:
    cmd_fxn_t lookup_c( char* name, int* num_words_ptr, char** argv, char* buf )
    {
      // Tokenizer format: tokenizer(char *string, char **argv, char *delims) --> argv[0] = 1st word in *string, etc
    
      const char* str = find_alias( name ) ;
      char* new_name ;
      char* new_copy ;
      char* str_tokens[ MAX_SENTENCE ] ;
      int str_num, i ;
      
      // If an alias is found, substitute the alias with the corresponding string, and change argv and num_words accordingly.
      if ( str )
        {
          // (Specs): "Make sure you don't leave any unfreed memory with your implementation."
    
          new_name = ( char* ) malloc( sizeof( char ) * MAX_WORD ) ;
    
          // Copy str to buf
          strncpy( buf, str, MAX_SENTENCE ) ;
    
          // Tokenize
          str_num = tokenizer( buf, str_tokens, " " ) ;
    
          // Set name
          strncpy( new_name, str_tokens[ 0 ], MAX_WORD ) ;
          name = new_name ;
          argv[ 0 ] = name ;
    
          // Copy argv's stuff
          for ( i = 1; i < *num_words_ptr; i++ )
    	{
    	  new_copy = ( char* ) malloc( sizeof( char ) * MAX_WORD ) ;
    	  strncpy( new_copy, argv[ i ], MAX_WORD ) ;
    	  str_tokens[ str_num + i - 1 ] = new_copy ;
    	}
    	
          argv = str_tokens ;
          *num_words_ptr = *num_words_ptr + str_num - 1 ;
    
          if (iAmDebugging)
    	{
    	  printf("argv[0]: %s\n", argv[0]) ;
    	  printf("argv[1]: %s\n", argv[1]) ;
    	  printf("argv[2]: %s\n", argv[2]) ;
    	  printf("num_words_ptr: %d\n", *num_words_ptr) ;
    	}
    
        }
    
      for ( i = 0; i < num_commands; i++ )
        if ( !strcmp( name, commands[ i ].name ) )
          { 
    	return commands[ i ].fxn;
          }
          
      // Command not found
      return NULL;
    }
    From the description, it seems they are telling me to copy things to the buffer and point things from argv to words in the buffer, but I don't see how that would be any different...

    To give an example of what it is doing, when there is some monster, for example,

    A goblin approaches!

    > alias c 'cast fireball'
    > alias
    c = 'cast fireball'
    > c goblin
    > You cannot cast goblin!

    The words[0] = cast and words[1] = goblin after the call to lookup... but words[0] = cast because it is connected to the argument: name.

    I went through gdb so many times my head is spinning. This is the output from lookup_command to main:

    Code:
    (gdb) 
    36: name = 0x8051ae0 "cast"
    21: commands[0] = {name = 0x804c945 "look", fxn = 0x804931e <look>, player_vulnerable = true}
    19: argv[2] = 0x8051b08 "donkey"
    18: argv[1] = 0xbffff701 "fireball"
    17: argv[0] = 0xbffff6fc "cast"
    16: *num_words_ptr = 3
    15: argv = (char **) 0xbffff210
    13: str_tokens[2] = 0x8051b08 "donkey"
    11: name = 0x8051ae0 "cast"
    10: str_tokens[1] = 0xbffff701 "fireball"
    9: str_tokens[0] = 0xbffff6fc "cast"
    7: str_num = 2
    6: buf = 0xbffff6fc "cast"
    5: new_name = 0x8051ae0 "cast"
    4: str = 0x8051540 "cast fireball"
    (gdb) 
    main (argc=1, argv=0xbffff9c4) at main.c:134
    35: num_words = 3
    34: words[2] = 0xbffff80f "mi"
    33: words[1] = 0xbffff7fe "donkey"
    32: words[0] = 0x8051ae0 "cast"
    29: argv[2] = 0xbffffb3d "ORBIT_SOCKETDIR=/tmp/orbit-ryan"
    28: argv[1] = 0x0
    27: argv[0] = 0xbffffb22 "/home/ryan/Code/proj1/game"
    23: num_words = 3
    22: buf2 = "cast\000fireball", '\000' <repeats 242 times>
    21: commands[0] = {name = 0x804c945 "look", fxn = 0x804931e <look>, player_vulnerable = true}
    1: command_name = 0xbffff7fc "c"
    Any help is appreciated...
    Last edited by Ryan.; 07-03-2010 at 10:18 PM.

  13. #13
    Registered User Ryan.'s Avatar
    Join Date
    Jul 2010
    Location
    Berkeley, CA
    Posts
    16
    Forget it.

    This loop fixed the assignment

    Code:
          for ( i = 0; i < *num_words_ptr; i++ )
    	argv[ i ] = str_tokens[ i ] ;
    I tried that before... it must have been something else broken in my code. Something that should have worked now works now that everything else is fixed
    Last edited by Ryan.; 07-04-2010 at 10:58 PM.

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You probably don't have time to fix this, but take it into account for the future:
    Code:
    cmd_fxn_t lookup_c( char* name, int* num_words_ptr, char** argv, char* buf )
    This is a big NO-NO. There are NO argument that specifies the size of these types. As such, you are simply screaming "buffer overrun" here.
    Add size argument of the buffers and do checks to make sure you don't read/write off the end. Make specialized of strcpy or use Microsoft's *_s functions is the best bet. It allows you to avoid buffer overruns easily and safely and also save you time in hunting down such bugs.

    Also, I see malloc in your code, but no free.

    For that matter, your function expects a pointer to pointer named argv, but it doesn't necessarily have to be argv. You can close argv, modify it to your will, and then pass it to your function.
    Safe. Simple. And best of all, it's guaranteed to work.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    Registered User Ryan.'s Avatar
    Join Date
    Jul 2010
    Location
    Berkeley, CA
    Posts
    16
    For that matter, your function expects a pointer to pointer named argv, but it doesn't necessarily have to be argv. You can close argv, modify it to your will, and then pass it to your function. Safe. Simple. And best of all, it's guaranteed to work.
    Thanks for your input. I am probably going to be marked down for not using free. Is it possible you can you explain more clearly what you mean by "close argv, modify it, and then pass it to the function"?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pointer assignment using array name
    By stavos77 in forum C Programming
    Replies: 7
    Last Post: 03-12-2010, 03:12 PM
  2. Compiling C in Visual Studio 2005
    By emanresu in forum C Programming
    Replies: 3
    Last Post: 11-16-2009, 04:25 AM
  3. Following CTools
    By EstateMatt in forum C Programming
    Replies: 5
    Last Post: 06-26-2008, 10:10 AM
  4. Quick question about SIGSEGV
    By Cikotic in forum C Programming
    Replies: 30
    Last Post: 07-01-2004, 07:48 PM
  5. assignment makes pointer from integer
    By crescen7 in forum C Programming
    Replies: 4
    Last Post: 06-25-2002, 10:08 PM