Thread: what is malloc doing?

  1. #1
    Registered User
    Join Date
    Nov 2010
    Posts
    21

    what is malloc doing?

    Hallo,
    I have the problem with the parsing of the http_proxy variable (see thread
    Now, in order to follow some best practices (at least that is what I have read), I need to use malloc before the usage of char * variables. Now, my variables are:
    Code:
    char *prxHostname, *envProxySrv, *envSproxySrv;
    and I retrieve them as:
    Code:
                if (getenv("http_proxy")){
                    envProxySrv=malloc(sizeof getenv("http_proxy")+1);
                    strcpy(envProxySrv, getenv("http_proxy"));
                }
                if (getenv("https_proxy")){
                    envSproxySrv=malloc(sizeof getenv("https_proxy")+1);
                    strcpy(envSproxySrv, getenv("https_proxy"));
                }
    It compiles just fine, but it crashes AFTER the execution of the aforementioned statements with the following error:
    Code:
    *** glibc detected *** ./programname: free(): invalid next size (fast): 0x08054a70 ***
    ======= Backtrace: =========
    /lib/libc.so.6(+0x6dffb)[0xb7606ffb]
    /lib/libc.so.6(+0x6ed7b)[0xb7607d7b]
    /lib/libc.so.6(cfree+0x6d)[0xb760badd]
    /lib/libc.so.6(+0x28f08)[0xb75c1f08]
    /lib/libc.so.6(+0x266dc)[0xb75bf6dc]
    /lib/libc.so.6(+0x25fff)[0xb75befff]
    /lib/libc.so.6(dcgettext+0x43)[0xb75bde53]
    /lib/libc.so.6(__strerror_r+0x5b)[0xb760f38b]
    /lib/libc.so.6(strerror+0x3a)[0xb760f28a]
    /lib/libcrypto.so.1.0.0(ERR_load_ERR_strings+0x12e)[0xb74565de]
    /lib/libcrypto.so.1.0.0(ERR_load_crypto_strings+0x14)[0xb7457604]
    /lib/libssl.so.1.0.0(SSL_load_error_strings+0x14)[0xb757b154]
    /usr/lib/libneon.so.27(+0x1bcc6)[0xb776acc6]
    /usr/lib/libneon.so.27(ne_sock_init+0x78)[0xb775f928]
    Naturally, I run the program in debug mode and I noticed that the prxProxySrv is assigned at the memory block 0x8054430
    From the netbeans memory monitor, I set that address and 64 bytes as the length and I have the following:
    Code:
    0x08054430  68 74 74 70 3A 2F 2F 31 30 2E 31 2E 33 2E 39 32  http://10.1.3.92
    0x08054440  3A 33 31 32 38 00 00 00 00 00 00 00 00 00 00 00  :3128...........
    0x08054450  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0x08054460  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    I was expecting the malloc of prsSproxySrv to be on the next free block, that of the "0x08054450"
    However, when the second malloc is executed, I have the following memory output:

    Next, I noticed that the following allocation:
    Code:
    0x08054430  68 74 74 70 3A 2F 2F 31 30 2E 31 2E 11 00 00 00  http://10.1.....
    0x08054440  3A 33 31 32 38 00 00 00 00 00 00 00 21 2E 39 32  :3128.......!.92
    0x08054450  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    0x08054460  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    So, with that mess, I find it completely natural to have issues with free() in an unknown location/library.

    So, what I am I doing wrong?

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> what is malloc doing?
    Wrong question. Try: "what is sizeof doing?"
    A: not what you think.

    gg

  3. #3
    Registered User
    Join Date
    Nov 2010
    Posts
    21
    Hmmm.
    Yeap, I got yout point. a printf("%d", sizeof getenv...) return 5, so, it's wrong. Should I use the following, then?
    Code:
    envProxySrv=malloc(sizeof getenv("http_proxy"))*strlen(getenv("http_proxy"))
    ????

    On the other hand, the problem is that the getenv returns char *, so the sizeof will return the size of the pointer...
    OK, I am lost not. How do I do that CORRECTLY?
    Last edited by tpe; 11-18-2010 at 08:27 AM.

  4. #4
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Why do you not create a static buffer large enough to hold your data, plus some extra, and copy the GetEnv() results into them?

    Code:
    #define MAX_ENVSTR 256
    
    char envProxyServ[MAX_ENVSTR + 1];
    
    strncpy(envProxyServ,GetEnv("HTTP_PROXY"),MAX_ENVSTR);
    Having a few extra bytes in the buffer is neither here nor there.
    Last edited by CommonTater; 11-18-2010 at 08:41 AM.

  5. #5
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> How do I do that CORRECTLY?
    strlen() + 1 will give the number of bytes to malloc.
    Or use strdup()/free()
    Or post #4 if you're comfortable with a bounded buffer.

    gg

  6. #6
    Registered User
    Join Date
    Nov 2010
    Posts
    21
    My thought was about the strlen. However, is stlen overflow safe?
    What do you mean by strdup()/free()?
    If you mean the "MAX_ENVSTR 256", I do not consider it as efficient way of programming. In reality, I could simply use the variable=value without major issues.

  7. #7
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by tpe View Post
    If you mean the "MAX_ENVSTR 256", I do not consider it as efficient way of programming.
    Actually using #define for buffer sizes is a very efficient way of doing things. Just think, if you find 256 is not enough you can change that one definition, recompile, and have a totally different buffer size, automatically throughout your entire program. 1 change, instead of (potentially) dozens of changes. There is no penalty in speed, size or complexity of compiled code... so what would be the downside?

    In reality, I could simply use the variable=value without major issues.
    Not with strings you won't. C doesn't assign strings with the equals sign, you need library functions for that and those functions will want a prepared memory buffer to put things into.

  8. #8
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    All you can do is rely on the manual:
    http://www.opengroup.org/onlinepubs/...ns/getenv.html

    It returns NULL or a NULL-terminated string. strlen() works fine on the latter.

    strdup() - http://www.opengroup.org/onlinepubs/...ns/strdup.html

    >> I could simply use the variable=value without major issues.
    Only if you never write to it, and never read from it again after calling getenv(), setenv(), or unsetenv().

    gg

  9. #9
    Registered User
    Join Date
    Nov 2010
    Posts
    21
    Why?
    getenv returns char*, as my variable is. So, effectively, when I write:
    Code:
    char *a, *b;
    a=b;
    all I am instructing the program to do is:
    copy everything from the pointer a to pointer b.
    So, I can do whatever I want with a and leave b on it's peace...

  10. #10
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> copy everything from the pointer b to pointer a
    The only thing that is copied is the address-value in b.

    http://www.cplusplus.com/doc/tutorial/pointers/

    gg

  11. #11
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    A pointer is like an entry in your address book. It merely contains the data to find somebody, it doesn't contain the actual contents and occupants of a house. Assigning pointer values is like copying an entry from one address book into another. You're only copying information on where to find the house, not the contents and occupants of the house. If you want to copy the contents of the "house" (in your case, the string that getenv is returning), you need to use something like strcpy or memcpy.

  12. #12
    Registered User
    Join Date
    Nov 2010
    Posts
    21
    OK, clear. But why is it working? I mean, when I use "=" I have no segmentation faults. With everything else (malloc, strdup, etc), I get some nice segmentation faults that are not very helpful...
    So, either gcc transparently does that (I doubt that!), or something else is happening...
    Last edited by tpe; 11-19-2010 at 12:32 AM.

  13. #13
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by tpe View Post
    Why?
    getenv returns char*, as my variable is. So, effectively, when I write:
    Code:
    char *a, *b;
    a=b;
    all I am instructing the program to do is:
    copy everything from the pointer a to pointer b.
    So, I can do whatever I want with a and leave b on it's peace...
    All you are doing is making a copy of the pointer... not a copy of the string.

    Since both pointers now point to the same place, anything you do to a will also affect b.

  14. #14
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by tpe View Post
    OK, clear. But why is it working? I mean, when I use "=" I have no segmentation faults. With everything else (malloc, strdup, etc), I get some nice segmentation faults that are not very helpful...
    So, either gcc transparently does that (I doubt that!), or something else is happening...
    The segfaults are probably because you haven't allocated memory to copy the data into.

    There are two easy ways to create a string buffer...

    Code:
    #define MAX_ENV 255;
    
    // first method
    char envStr[MAX_ENV];
    
    // second method
    char *envStr = malloc(MAX_ENV * sizeof(char));
    Both result in a string buffer of 255 characters... the first method creates the buffer on the program's stack the second creates it in the "heap" memory shared by all programs.

    In either case you can use strcpy() or memcpy() to safely make a duplicate of your string.

  15. #15
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094
    No need to sizeof char since it's always going to be 1, but I guess that's the more general way of malloc-ing if you had something other than char.
    1. Get rid of gets(). Never ever ever use it again. Replace it with fgets() and use that instead.
    2. Get rid of void main and replace it with int main(void) and return 0 at the end of the function.
    3. Get rid of conio.h and other antiquated DOS crap headers.
    4. Don't cast the return value of malloc, even if you always always always make sure that stdlib.h is included.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. What does Malloc do?
    By Albinoswordfish in forum C Programming
    Replies: 4
    Last Post: 03-10-2010, 06:23 AM
  2. malloc + segmentation fault
    By ch4 in forum C Programming
    Replies: 5
    Last Post: 04-07-2009, 03:46 PM
  3. Is there a limit on the number of malloc calls ?
    By krissy in forum Windows Programming
    Replies: 3
    Last Post: 03-19-2006, 12:26 PM
  4. Malloc and calloc problem!!
    By xxhimanshu in forum C Programming
    Replies: 19
    Last Post: 08-10-2005, 05:37 AM
  5. malloc() & address allocation
    By santechz in forum C Programming
    Replies: 6
    Last Post: 03-21-2005, 09:08 AM

Tags for this Thread