From: "Nakada, Nobuyoshi" Date: 2005-05-18T17:44:38+09:00 Subject: Re: IRB, Mac OS X, command-line require via "-r" and Bus Errors Hi, At Wed, 18 May 2005 16:20:13 +0900, Jonathan Paisley wrote in [ruby-talk:143017]: > > No, it duplicates the argument strings and remains them in the > > original argv (i.e., pointed from *_NSGetArgv()), but let the > > entire string area to be pointed by newly allocated argv, which > > is returned to the caller. > > The effect your describe is right, but my point is that set_arg0 (defined > in ruby.c) needs to operate on the original argv in order to be able to > change the process name as reported by 'ps'. If set_arg0 sees strdup()-ed > strings, its changes will have no effect. Caller's argv is changed but *argv isn't changed. Pointers pointed by original argv are changed. The pointers are not important. +-----+-----+-----+-----+-----+ ,-- | 0 | 1 | 2 | 3 | 4 | <----- original argv | +--|--+--|--+--|--+--|--+--|--+ | | | | | | | V V V V V ,-|- "./argv" "a" "b" "c" NULL <----- original strings | | ~~|~|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | "./argv" "a" "b" "c" NULL <----- duplicated strings | | A A A A A | | | | | | | | | +--|--+--|--+--|--+--|--+--|--+ | `-> | 0 | 1 | 2 | 3 | 4 | <----- original argv kept | +-----+-----+-----+-----+-----+ in the runtime internal | `--> "./argv" "a" "b" "c" NULL <----- original strings A A A A A in the system area | | | | | +--|--+--|--+--|--+--|--+--|--+ | 0 | 1 | 2 | 3 | 4 | <----- duplicated argv returned +-----+-----+-----+-----+-----+ to the caller. $ cat argv.c #include "ruby.h" #undef xmalloc #define xmalloc malloc void ruby_sysinit(argc, argv) int *argc; char ***argv; { int i, n = *argc, len = 0; char **v1 = *argv, **v2 = ALLOC_N(char*, n + 1); MEMCPY(v2, v1, char*, n); v2[n] = 0; for (i = 0; i < n; ++i) { v1[i] = strdup(v1[i]); } *argv = v2; } void dump_argv(name, argc, argv) char *name; int argc; char **argv; { int i; printf("%s: argc=%d argv=%p\n", name, argc, argv); for (i = 0; i < argc; ++i) { char *arg = argv[i]; printf("argv[%d] = %p \"%s\"\n", i, arg, arg); } } int main(argc, argv) int argc; char **argv; { int origargc = argc; char **origargv = argv; dump_argv("before", argc, argv); ruby_sysinit(&argc, &argv); dump_argv("after", argc, argv); dump_argv("original", origargc, origargv); return 0; } $ make argv.o && gcc -o argv argv.o $ ./argv a b c before: argc=4 argv=0x61813d80 argv[0] = 0x61813dc8 "./argv" argv[1] = 0x61813df0 "a" argv[2] = 0x61813e08 "b" argv[3] = 0x61813e20 "c" after: argc=4 argv=0xa050008 argv[0] = 0x61813dc8 "./argv" argv[1] = 0x61813df0 "a" argv[2] = 0x61813e08 "b" argv[3] = 0x61813e20 "c" original: argc=4 argv=0x61813d80 argv[0] = 0xa0505c0 "./argv" argv[1] = 0xa0505d0 "a" argv[2] = 0xa0505e0 "b" argv[3] = 0xa0505f0 "c" -- Nobu Nakada