Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Are capturing lambdas supported? #3

Open
SelfishOlex opened this issue Jun 6, 2024 · 2 comments
Open

Are capturing lambdas supported? #3

SelfishOlex opened this issue Jun 6, 2024 · 2 comments

Comments

@SelfishOlex
Copy link

With the default configuration the following code segfaults:

TEST_CASE("Delegate test with large capture")
{
    int a = 0, b, c, d;
    delegate::Delegate<void> test([&a, &b, &c]()
    {
        a = 1;
    });

    test();

    REQUIRE(a == 1);
}

Until I increase DELEGATE_ARGS_SIZE.

#define DELEGATE_ARGS_SIZE sizeof(int) + sizeof(int *) /* + N */

So it seems to work when the capturing lambda only captures 2 words worth of memory. Is this working as intended?
Or should I expect lambdas of any size to fail at some point in the future for me?

Thanks!

@bitwizeshift
Copy link
Owner

bitwizeshift commented Jun 9, 2024

Hi @SelfishOlex. It's been a while since I have worked on this project, but the syntax and naming in this issue doesn't look like it's from this repo.

Have you made any changes or altered the implementation in any way? This implementation uses "bind" non-member functions to create delegate bind targets, and the naming is all in lowercase rather than in Camelcase. Additionally there is no DELEGATE_ARGS_SIZE definition since it's done using constexpr rather than a macro.

The specific case in question regarding large captures should be both supported and fully guarded by SFINAE size checks for the internal capacity -- but it is always a referential capture to the functor/lambda object, meaning the functor/lambda must outlive the delegate. This is denoted by a capture by pointer, rather than implicit by reference -- so it usually become pretty clear at the call site.

I can double check when I am back in front of a computer, but I believe you have the wrong project.

@bitwizeshift
Copy link
Owner

bitwizeshift commented Jun 9, 2024

I did a quick search, and I suspect you may be confusing this project with https://github.com/bdiamand/Delegate -- which has delegate::Delegate (rather than cpp::delegate). If this is correct, you might want to ask there! Reading the header, this sounds like they expect it. From delegate.hpp:52:

 *      (Con) Unable to store arbitrary sized captures - captures must fit the compile-time delegate size

That said, I just wanted to give a word of caution: there are a lot of C++ projects out there based on half-understood myths about C++, and this can lead to a lot of problems when it comes to low-level manipulations. What you're hitting sounds like a pretty critical issue relating to undefined behavior, and that's not a good thing to be able to slip in at runtime. Good software should prevent this statically at compile-time.

A segfault is a best-case scenario for such a situation, because it can be even worse if it leads to buffer-overwrite issues, or alignment issues -- in which case your program may behave differently on different executions and lead to very different behaviors.

This isn't a plug for my project at all, though this is prevented statically in this implementation; it's just a general word of caution when jumping into small projects in the C++ ecosystem. There's "C++: The real standard", and "C++: The myth" where developers like to pretend the hard-limits of the standard don't exist because "it runs on my machine" -- and this simply doesn't work for production code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants