0

I'm trying to get current local time in C++ with the following code:

time_t rawtime;
struct tm * timeinfo;

time (&rawtime);
timeinfo = localtime (&rawtime);

Unfortunately, I'm getting "debug assertion failed" when calling localtime (somewhere in __getgmtimebuf -> _malloc_crt) with the message _BLOCK_TYPE_IS_VALID(pHead->nBlockUse).

Am I missing something, do I need some compile flag (I'm using vs 2012 with c++11)?

If not, what alternative do I have?


I cannot post the entire code and it's not easy to isolate more of the context. It seems that the error is not from the time functions but from the rest of the logic (as they work in a separate project) and I will try to find what's causing it but still, I feel that the error is kinda obscure.

What I was doing was something like this:

#include <iostream>
#include <chrono>
#include <ctime>
#include <string>
#include <thread>

class A
{
public:
    void time()
    {   
        //time_t rawtime;
        //struct tm * timeinfo;

        //time (&rawtime);
        //timeinfo = localtime (&rawtime);

        time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
        std::cout << std::ctime(&now);
    }
};

class B
{
public:
    void run(A *a)
    {       
        this->a = a;

        this->t = new std::thread(t_f, *this);
        this->t->join();
    }

    ~B()
    {
        delete t;
        delete a;
    }

    friend void t_f(B &b);

private:
    A *a;
    std::thread *t;
};

void t_f(B &b)
{
    b.a->time();
}


int main()
{
    B b;
    b.run(new A());

    return 0;
}

What I didn't know is that the destructor of B was called before the join and before the thread finished its job.

SOLUTION:

  • the time functions (whether from ctime or chrono) work as expected
  • pass B to t_f() by pointer or std::ref

Both suspicions from Keith Thompson and Mats Petersson were grounded and correct so I will mark Keith's answer correct as it was the first good lead to solve this obscure error even though I didn't present enough informations initially.

Thank you

Community
  • 1
  • 1
Dan
  • 1,555
  • 2
  • 14
  • 30
  • 1
    There is entire new time library in C++11 - ``. But you're using VS2012, and I don't know how well it supports this library. – milleniumbug Aug 17 '13 at 20:45
  • You might need to check that the `time` call actually succeeded, by checking the return value of it. If the call fails the value of `rawtime` is undefined, and might be an invalid time stamp. – Some programmer dude Aug 17 '13 at 20:46
  • What does "time (&rawtime);" do ? –  Aug 17 '13 at 20:52
  • 1
    @DieterLücking See any reference, e.g. [this one](http://en.cppreference.com/w/c/chrono/time). – Some programmer dude Aug 17 '13 at 20:53
  • 1
    works ok for me (VS2012 too). Can you put a full example? – Gabriel Aug 17 '13 at 20:56
  • My "man 3 time" is showing nothing (ubuntu) –  Aug 17 '13 at 20:57
  • 1
    Reading the error message more closely, it seem you are corrupting memory somewhere. You probably have a bug somewhere in your code where you write over (or under) the bounds of something. – Some programmer dude Aug 17 '13 at 20:59
  • @DieterLücking Have you installed the development manual pages? Otherwise just follow the link in my previous comment. Also, it's in section 2 of the manual pages (e.g. `man 2 time`) – Some programmer dude Aug 17 '13 at 20:59
  • It seems sometimes it works (I'm referring to both portions of code) sometimes it doesn't. It's not reliable. – Dan Aug 17 '13 at 21:21
  • Visual studio 2012 supports std::chrono reasonably well. http://msdn.microsoft.com/en-us/library/hh874757.aspx http://en.cppreference.com/w/cpp/chrono – kfsone Aug 17 '13 at 20:53
  • @user2704 That is a sure sign of you doing something that leads to *undefined behavior*. Writing outside the bounds of an array or outside of allocated memory is a possibility, especially considering the error message. You should look over loop conditions so the go from zero to one less than the size etc. – Some programmer dude Aug 18 '13 at 08:26

2 Answers2

4

There are alternatives to localtime, but that's not the point you should focus on.

I copied your code into a small program:

#include <ctime>
#include <iostream>
int main(void) {
    time_t rawtime;
    struct tm * timeinfo;

    time (&rawtime);
    timeinfo = localtime (&rawtime);

    std::cout << "rawtime = " << rawtime << "\n";
    std::cout << "Welcome to " << 1900 + timeinfo->tm_year << "\n";
}

and it compiles and runs without error:

rawtime = 1376773717
Welcome to 2013

The error message you're getting seems to indicate a memory allocation problem. It's likely that the localtime function uses malloc internally. If malloc fails because there isn't enough memory available, it returns a null pointer, which localtime should be able to handle. The assertion error probably indicates that the heap is corrupted -- which means that something else in your program has done something bad, perhaps freeing memory that you didn't allocate or writing past an array bound and clobbering information the system uses to keep track of things.

Switching from <ctime> to <chrono> might be a good idea by itself, but it's not the solution to your problem. You need to track down and correct whatever your program is doing that corrupts the heap.

UPDATE :

Since the solution should be in an answer, not in the question, I'm copying this here from the question:

What I didn't know is that the destructor of B was called before the join and before the thread finished its job.

SOLUTION:

  • the time functions (whether from ctime or chrono) work as expected
  • pass B to t_f() by pointer or std::ref

Both suspicions from Keith Thompson and Mats Petersson were grounded and correct so I will mark Keith's answer correct as it was the first good lead to solve this obscure error even though I didn't present enough information initially.

Community
  • 1
  • 1
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • Indeed it seems sometimes it works other times not (both ctime as well as chrono functions). – Dan Aug 17 '13 at 21:23
  • @user2704: Which means there's a bug in your program, and it's in code that you haven't shown us. If you can narrow your program down to a sufficiently small *complete* example that exhibits the bug, and update your question to show it, then we may be able to help. Otherwise all we can tell you is "there's a bug somewhere, and you need to fix it". – Keith Thompson Aug 17 '13 at 21:25
  • 1
    @user2704: When I wrote the previous comment, I hadn't seen your updated question. But you need to copy-and-paste the *exact* code. What you posted doesn't compile; you have a typo, `time_str_2` vs. `time_str2`. When I fix that, your program works for me. And please update your question to show us *what that program does*; as it stands, I have no idea whether or not it works for you. – Keith Thompson Aug 17 '13 at 21:28
  • Can then someone please provide alternatives to localtime? The title of the question is completely misleading. :( – PaulProgrammerNoob Jan 06 '20 at 20:26
  • @PaulProgrammerNoob You might want to post a new question. Posting a comment on a resolved question from 6+ years ago is less likely to get you a useful answer. In your new question, please explain why you need an alternative (i.e., what you need that `localtime` doesn't provide). – Keith Thompson Jan 06 '20 at 20:52
1

When you get "__getgmtimebuf -> _malloc_crt) with the message _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)", this nearly always means that some OTHER function has called free on a block that wasn't allocated with new/malloc, or that something is overwriting the end of the buffer of an allocated block. Another possibility is "used after free", which can appear in a similar manner.

I would concentrate on what happens BEFORE you call the time functions. It is highly likely something simple - it's just the deviousness of certain types of heap corruption that you don't discover it until much later.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227