memory leak with localtime()?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Avaenuha
    New Member
    • Apr 2007
    • 19

    memory leak with localtime()?

    I have a program that's simulating a POS system, and it writes every sale to a sales log, along with the timestamp. To get the timestamp, I'm passing a time_t struct through localtime(), and passing that through strftime.

    However, when i run my program thorugh bcheck, I get:
    ---------
    Blocks in use report (blocks in use: 1 total size 10428 bytes)
    Allocation Call Stack:
    get_zone < getsystemTZ < _localtime_r < printLog < purchase < main
    -----------------
    (obviously main, purchase and printlog are my functions)

    Anyone know what's going on, here? Surely the standard library wouldn't have leaks?
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    Could we see the call, please? And perhaps the variables used as arguments.

    Comment

    • dumparun
      New Member
      • Feb 2007
      • 26

      #3
      Originally posted by Avaenuha
      I have a program that's simulating a POS system, and it writes every sale to a sales log, along with the timestamp. To get the timestamp, I'm passing a time_t struct through localtime(), and passing that through strftime.

      However, when i run my program thorugh bcheck, I get:
      ---------
      Blocks in use report (blocks in use: 1 total size 10428 bytes)
      Allocation Call Stack:
      get_zone < getsystemTZ < _localtime_r < printLog < purchase < main
      -----------------
      (obviously main, purchase and printlog are my functions)

      Anyone know what's going on, here? Surely the standard library wouldn't have leaks?
      i dont know the API,
      but my guess...
      there are API's which allocates the memory and return back a populated structure with the size.
      its the duty of the user to deallocate the memory.
      please check your API doc.

      Comment

      • Avaenuha
        New Member
        • Apr 2007
        • 19

        #4
        I've tried deallocating everything I could think of to do with it, and all i end up with is 'bad frees' ... the manpage doesn't specify anything from locatime() needs to be deallocated afterwards, either (you're not mallocing, so why would you need to free?) - though I can't get a man reference for get_zone, getsystemTZ or _localtime_r.

        The call is:
        Code:
           char timeString[TIMESTAMP_LEN];
           char *format = {"%a %b %d %H:%M:%S %Y"};
           struct tm *converted;
           time_t now;
        
           time(&now);
           converted = localtime(&now);
           strftime(timeString, TIMESTAMP_LEN, format, converted);

        Comment

        • weaknessforcats
          Recognized Expert Expert
          • Mar 2007
          • 9214

          #5
          This code:
          Code:
          char timeString[TIMESTAMP_LEN];
             char *format = {"%a %b %d %H:%M:%S %Y"};
             struct tm *converted;
             time_t now;
          
             time(&now);
             converted = localtime(&now);
             strftime(timeString, TIMESTAMP_LEN, format, converted);
          works fines. There are no free() calls because there are no malloc() calls. The tm variable used by the time functions is static and is used by all time functions.

          You aren't using multiple threads are you?

          Comment

          • Avaenuha
            New Member
            • Apr 2007
            • 19

            #6
            Originally posted by weaknessforcats
            This code:
            Code:
            char timeString[TIMESTAMP_LEN];
               char *format = {"%a %b %d %H:%M:%S %Y"};
               struct tm *converted;
               time_t now;
            
               time(&now);
               converted = localtime(&now);
               strftime(timeString, TIMESTAMP_LEN, format, converted);
            works fines. There are no free() calls because there are no malloc() calls. The tm variable used by the time functions is static and is used by all time functions.

            You aren't using multiple threads are you?
            No multple threads. And it *works* no problem. But if you run it under bcheck -all, you'll find after the program has exited, there's a "block still in use" because of the function - if it's just a static variable, shoudln't it be discarded when the program ends?. Now, this is an assigment where I'll have marks deducted for "memory issues", but I can't work out a) why it does this, or b) what I can do about it.

            Comment

            • MattFL
              New Member
              • May 2008
              • 1

              #7
              I get the same exact error using Visual Studio 2005 and CompuWare Bounds Checker. At least on this platform, I think the secret is in the runtime library. In particular in the function __getgmtimebuf( ).

              A call to localtime() definitely results in allocated memory, it's allocated in __getgmtimebuf( ) as shown below (look for _malloc_crt()). What happens is the library will allocate memory on the first call, then keep a pointer to the allocated memory and not allocate it a second time. This is why you should NOT free the pointer returned to you by localtime(). If you do, then you'll end up with all sorts of randomness on successive calls to localtime(), and if you try to free the pointer returned by localtime() a second time you'll get a debug run time error about a bad pointer (notice every time you call localtime() you're returned a pointer to the same address). Also notice that if you free the pointer, then call localtime() again, your memory check tool isn't catching the fact that the library is now writing to unallocated memory! These tools are not perfect..

              So I think you've got 1 of two situations: (a) There really is a leak and it's in the library, or (b) the library is cleaning up but for some reason our tools aren't catching it. Checking out the source for the library would give you the definite answer, unfortunately I don't have time at the moment to do this myself.

              stack:
              • __getgmtimebuf
              • _localtime32
              • localtime <----- returns pointer to memory allocated in __getgmtimebuf


              Code:
              struct tm * __cdecl __getgmtimebuf ()
              {
              
                      REG2 struct tm *ptb;            /* will point to gmtime buffer */
                      _ptiddata ptd = _getptd_noexit();
                      if (!ptd) {
                          errno = ENOMEM;
                          return (NULL);
                      }
              
                      /* Use per thread buffer area (malloc space, if necessary) */
              
                      if ( (ptd->_gmtimebuf != NULL) || ((ptd->_gmtimebuf =
                          _malloc_crt(sizeof(struct tm))) != NULL) )
                              ptb = ptd->_gmtimebuf;
                      else
                      {
                          errno = ENOMEM;
                      }
                      return ptb;
              }

              Comment

              • RRick
                Recognized Expert Contributor
                • Feb 2007
                • 463

                #8
                When I first looked at localtime, it looked like it was leaking memory by returning a pointer value to a structure tm. The linux man pages claim that that localtime returns the following
                The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions
                Another test would be to the the localtime_r routine instead. This has the added benefit of being thread safe, ands puts the results in a structure you pass to it.

                BTW: Is much being leaked? Does it grow over time?

                Comment

                • valdemarpavesi
                  New Member
                  • Dec 2008
                  • 1

                  #9
                  Hello

                  any final conclusion here :

                  I do see the same equivalent problem 88 buffers allocated with 16384 bytes each one:



                  umem_alloc_1638 4 leak: 88 buffers, 16384 bytes each, 1441792 bytes total
                  ADDR BUFADDR TIMESTAMP THREAD
                  CACHE LASTLOG CONTENTS
                  5d78c0 5ec000 322e2df09fc1a 1
                  468468 43ed80 0
                  libumem.so.1`um em_cache_alloc_ debug+0x12b
                  libumem.so.1`um em_cache_alloc+ 0xc8
                  libumem.so.1`um em_alloc+0xaf
                  libumem.so.1`ma lloc+0x2e
                  libc.so.1`get_z one+0x55
                  libc.so.1`getsy stemTZ+0xad
                  libc.so.1`local time_r+0x2b
                  libc.so.1`local time+0x36
                  tzMgmtDB::calcT ZOffSet+0x1c2
                  tzMgmtDB::updat eTZRelativeTime +0x298
                  main+0x83d
                  _start+0x6c

                  >


                  Thanks!
                  Valdemar
                  Last edited by valdemarpavesi; Nov 12 '09, 10:05 PM. Reason: name

                  Comment

                  Working...