Thread: how to change static char* and not lose mem ?

  1. #1
    Registered User
    Join Date
    Apr 2007
    Posts
    111

    how to change static char* and not lose mem ?

    Hello ,...

    im working on a patch to smser (smser.sf.net)project.
    since i don't how the change of static char* = " ... " to char * Iam avoiding the change in the main program .

    in the program there are sevral static char varibales that need to ne changed:

    orignal code :
    Code:
    static char* CONFDIR = "/.centericq";
    i wish to change it by a function so i do the next. // since diffrent users will run the program from diffrent places .

    Code:
    #include <pwd.h>
    #include <errno>
    #include <assert>
    
    int change_path()
    {
       char *path_to_home = NULL;
       char *temp;
    
       temp        = CONFDIR;
       path_to_home = get_home_dir();
    
       CONFDIR = (char *) malloc ( sizeof(char) * ( strlen(path_to_home) + strlen(temp) + 1));
       strcpy(CONFDIR,path_to_home);//copy the actual path to confdir
       strcpy(CONFDIR + strlen (path_to_home),temp);
    
       free(path_to_home);
    
       return 0;
    }
    
    char* get_home_dir()
    {
       char *path = NULL;
       int size = 0;
    
       struct passwd *passwd; //read man file for getpuid() or 
    
       passwd = getpwuid(getuid());
       size = strlen((passwd->pw_dir));
       path = (char *) malloc (sizeof(char) *  size);
       assert(path);
       strcpy(path, passwd->pw_dir); //will copy the home directory to path
       /*
        * maybe just returning the pw_dir ?
        */
      return path; 
    }
    p.s.
    im writing from the memory so maybe i wrote some small errors (but this is the genral idea).

    is it the right attiude with code changes ? (to write small functions expect changing in the main program).
    why Gaos didn't had a wife ?
    http://bsh83.blogspot.com

  2. #2
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    You're asking how you can change a static char variable?

    You don't. Just don't make it static if you want to change it.

  3. #3
    Registered User
    Join Date
    Apr 2007
    Posts
    111
    it is in the orignal code stated as static and i don't know what will heppen if i change the static char * something to char *
    why Gaos didn't had a wife ?
    http://bsh83.blogspot.com

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    static in C is used for two things (and in C++ as well, but it has further uses in C++, which I'm not going into here):

    Outside a function, static is used to tell the compiler "This is a local <something> in this object file, don't let anyone see it".

    Inside a function, it essentially makes a variable "global", but still only visible to the function. What I mean by this is that normally, local variables are "auto", meaning that they are created when the function is called and destroyed when the function returns. By adding static, the variable stays in a permanent place in memory, whether the function is in use at the time or not.

    Examples:
    Code:
    static int x = 47;
    
    static char *str = "Some data";
    
    int next_int(void)
    {
       static int x = 0;   // This will be incremented, so function will return 1, 2, 3, ...
       x++;
       return x;
    }
    
    static int some_func(void)  ...  // This function can ONLY be used from source that can "see" this function, so you can't call it from a different .C file [1]
    [1] This assumes that we don't have any include of .C files - it is possible to include .C files, but as a general rule, it's not good style.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    You shouldn't need to. I think you're confusing static and const.
    Static just means that memory for this variable is allocated in the global area of memory management (there's actually a lot more about static, but that's the general idea)

    Leave the static in and compile your code, it should work. If not, post the ouput of the compiler here.

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  6. #6
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    and don't cast malloc() or Salem will punish you.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    The 'static' just alters it's scope, so that other modules cannot see it.
    Within the module, you can still reassign it to point to another place in memory.
    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
    Join Date
    Apr 2007
    Posts
    111
    Quote Originally Posted by cpjust View Post
    and don't cast malloc() or Salem will punish you.
    Thnx i studied some thing new ..
    now for the casting itself real nice post i found ( http://cboard.cprogramming.com/showthread.php?t=25799 ).

    so i don't need to do the malloc at all (?) since if i try to use strcpy ill get sigsegv:

    Code:
    #include <stdio.h>
    #include <pwd.h>
    #include <errno.h>
    #include <assert.h>
    
    static char* CONFDIR = ".123";
    static char* CONfy   = ".2";
    char* get_home_dir();
    
    int change_path()
    {
       char *path_to_home = NULL;
       char *temp;
    
       temp        = CONFDIR;
       path_to_home = get_home_dir();
    
       //CONFDIR = malloc ( sizeof(CONFDIR) * ( strlen(path_to_home) + strlen(temp) + 1));
       strcpy(CONFDIR,path_to_home);//copy the actual path to confdir
       strcpy(CONFDIR + strlen (path_to_home),temp);
       
       return 0;
    }
    
    char* get_home_dir()
    {
       char *path = NULL;
       int size = 0;
    
       struct passwd *passwd; //read man file for getpuid() or 
    
       passwd = getpwuid(getuid());
       size = strlen((passwd->pw_dir));
         return passwd->pw_dir;
     }
     
     int main()
     {
    	 change_path();
    	
    	 return 0;
     }
    since CONFDIR is equalled to const string (?).

    p.s.
    Thnx about the casting ..
    why Gaos didn't had a wife ?
    http://bsh83.blogspot.com

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    > so i don't need to do the malloc at all (?) since if i try to use strcpy ill get sigsegv:
    Yes, you need the malloc, but you don't need to cast the pointer type.

    If you're getting warnings about not being able to cast a void*, then that means you're using a C++ compiler to compile your C code. Either use 'new' for memory allocation, or fix which compiler you run.

    As for the segfault, this is because you're trying to modify a "string constant". These are typically marked as read-only by the operating system. Any attempt to modify them (say strcpy) will immediately end your program.
    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.

  10. #10
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Right, you don't need to cast malloc at all. It's because it returns a void pointer, which can be assigned to any other pointer without a cast. In K&R (the original) C, there was no such thing as a void pointer, so malloc() and calloc() and realloc() returned char * pointers, which needed to be casted. No longer.

    Also, C++ doesn't allow assigning any old pointer to a void pointer without a cast.

    You still need the malloc(), though. You can't strcpy() something to a string literal like ".123".

    Might I suggest using this?
    Code:
    static char* CONFDIR = "~/.centericq";
    Then you wouldn't have to change it . . .
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  11. #11
    Registered User
    Join Date
    Apr 2007
    Posts
    111
    using "~... " will result in error since this sign is changed by the shell and will not work fine in any one .
    why Gaos didn't had a wife ?
    http://bsh83.blogspot.com

  12. #12
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Yes, you're right, sorry.

    Code:
    strcpy(CONFDIR + strlen (path_to_home),temp);
    That's the same as
    Code:
    strcpy(CONFDIR, temp);
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  13. #13
    Registered User
    Join Date
    Apr 2007
    Posts
    111
    moment i thouth that if i strcpy from ptr + some amout of bytes ill start with the offset i added

    Code:
    void fooman()
    {
       char *foo;
       foo = malloc (sizeof(foo) * 5+ 1);
       strcpy(foo,"foobar");
       printf("&#37;s",foo); // foobar
       strcpy(foo + 3,"bar");
       printf("%s","sal");//foosal
       free(foo);
    }
    am i wrong ?
    Last edited by jabka; 09-07-2007 at 05:01 PM.
    why Gaos didn't had a wife ?
    http://bsh83.blogspot.com

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Now, the way I would solve the "gethomedir" is to pass in a fixed size array with a size of MAX_PATH (include limits.h). That is the number of chars that the longest filename and path is allowed to be.

    Code:
       foo = malloc (sizeof(foo) * 5+ 1);
    This allocates, on a 32-bit system, 21 bytes. I expect you actually wanted to say:
    Code:
       foo = malloc (sizeof(*foo) * 6+ 1);
    I thik dwks means
    Code:
    strcpy(x + strlen(x), b);
    // is the same as:
    strcat(x, b);
    Strcat will probably be a tiny bit more efficient unless you need to strlen the first string anyways (if you do need strlen of the first string, it's obviously good to avoid doing strcat later, which will count the chars in the string again).

    --
    Mats

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #15
    Registered User
    Join Date
    Apr 2007
    Posts
    111
    i use this solution since i use the passwd->pw_dir and copy it to the begning of CONFDIR.
    but the size of CONFDIR is bigger then passwd->pw_dir .
    why Gaos didn't had a wife ?
    http://bsh83.blogspot.com

Popular pages Recent additions subscribe to a feed