jstedfast / gmime

A C/C++ MIME creation and parser library with support for S/MIME, PGP, and Unix mbox spools.
GNU Lesser General Public License v2.1
113 stars 36 forks source link

messages still persist even after unref #75

Closed ItsShadowl closed 4 years ago

ItsShadowl commented 4 years ago

bool parse_message(std::string strMsg) {
    GMimeMessage* message;
    GMimeStream* stream;
    GMimeParser* parser;
    GMimeParserOptions* options;

    g_mime_init();

    stream = g_mime_stream_mem_new_with_buffer(strMsg.c_str(), strMsg.length());
    parser = g_mime_parser_new_with_stream(stream);

    message = g_mime_parser_construct_message(parser, NULL);

    const char* subject = g_mime_message_get_subject(message);
    const char* body = g_mime_message_get_body(message);
    if (in_array(std::string(subject), possibleSubjects))
    {
        std::cout << g_mime_message_get_body(message) << std::endl;
        g_object_unref(stream);
        g_object_unref(parser);
        g_object_unref(message);
        return true;
    }
    g_object_unref(stream);
    g_object_unref(parser);
    g_object_unref(message);
    g_mime_shutdown();
    return false;
}
for (size_t i = result.size() - 10; i < result.size(); i++) {
            std::string strMsg;
                       IMAPClient.GetString(result[i], strMsg);
            if (parse_message(strMsg)) {
                std::cout << +"\n\n\n --------- " + result[i] + "\n : \n\n" << std::endl;
                    std::cout << strMsg << std::endl;
            }
        }

the parse_message get different strMsg from my IMAP Client, but after looping; the first one is the only one messages that get persisted

jstedfast commented 4 years ago

Don't init and shutdown the gmime library for each message. The library is not designed to do that.

The g_mime_init() method should only be called once and g_mime_shutdown() should only be called once.

I'm not sure how you're deciding that the message is not cleaned up after unreffing it, but it probably has something to do with the memory corruption you are causing by all those calls to init/shutdown.

ItsShadowl commented 4 years ago

I added the init and shutdown later when i figured it wasn't returning what i was expecting..

jstedfast commented 4 years ago

Can you explain to me how you came to the conclusion that the GMimeMessage is not being cleaned up?

Or are you talking about the first (and only) instance of GMimeMessageClass? Because that's how GObject classes work - one gets allocated and never cleaned up. All GMimeMessage objects share the same allocated GMimeMessageClass.

ItsShadowl commented 4 years ago

I eventually gave up on it, but try looping multiple MIME strings, by getting each subjects... You would figure out what i meant...

The project got stopped, eventually because we couldn't get this part right...

After looping the second time, the Message class still have the old message instead.

jstedfast commented 4 years ago

I eventually gave up on it, but try looping multiple MIME strings, by getting each subjects... You would figure out what i meant...

You're not making any sense to me. What would I look for? Please provide a sample test case with some message strings for the parser so that I can see what you are seeing.

I already have unit tests that parse multiple messages and verify that the subjects/etc are correct, so there must be more to the issue than just parsing multiple messages and looking at their subjects.

What am I missing?

The project got stopped, eventually because we couldn't get this part right...

Sorry to hear that, but GMime is open source so you could have stepped through it with a debugger. You also could have filed an issue like this one sooner and provided me with test cases and I might have been able to steer you in the right direction if it is your code that is broken or fixed GMime if it truly is a bug in GMime's code.

After looping the second time, the Message class still have the old message instead.

Message class? Or message object? The GMimeMessageClass struct is only allocated once (in g_mime_init()) for the lifetime of the program because it only has the virtual method tables. That's how GObject classes work.

If I assume you mean object instead of class, well, that doesn't happen in any of my own unit tests, so again, I'm just not seeing what you're seeing. It could be that my unit tests don't test a particular scenario that you are hitting, but we will never know unless you provide some test cases for me to look at.

ItsShadowl commented 4 years ago

I will wake some parts of the project to prove if its my bug or not, perhaps it might be a bug from my PC environment as i copied the code from one of the test files...

I would urge you disregard my issues till i can prove it, i should get some test codes and share it here if same bug happen elsewhere, then it can be regarded as a bug...

I would get back on the issue before the end of the week, hopefully.