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

offset_of! overflows stack when called on BIG structs #22

Closed
LoganDark opened this issue Nov 15, 2021 · 6 comments
Closed

offset_of! overflows stack when called on BIG structs #22

LoganDark opened this issue Nov 15, 2021 · 6 comments

Comments

@LoganDark
Copy link

image

I'm trying to initialize a struct on the heap, but field-offset just overflows the stack whenever I try to get the field offset xD

@Diggsey
Copy link
Owner

Diggsey commented Nov 15, 2021

I'm guessing Self is an extremely large struct? Do you get the same stack overflow if you compile with optimizations enabled?

I think the answer here is going to be: don't use offset_of! with a struct so huge that it won't fit on the stack. In general such types are quite impractical to use with Rust anyway, since there's no stable in-place construction.

@LoganDark
Copy link
Author

LoganDark commented Nov 15, 2021

I'm guessing Self is an extremely large struct? Do you get the same stack overflow if you compile with optimizations enabled?

Looks like going into release mode fixes the stack overflow. So in order to test with debug assertions, I'd have to tweak an existing profile. I guess it works.

I think the answer here is going to be: don't use offset_of! with a struct so huge that it won't fit on the stack. In general such types are quite impractical to use with Rust anyway, since there's no stable in-place construction.

Isn't that a pretty big use-case for field-offset, though? Manually writing to struct fields that can't be accessed through a reference?

@Diggsey
Copy link
Owner

Diggsey commented Nov 16, 2021

Manually writing to struct fields that can't be accessed through a reference?

I'm not sure what you mean by this? References can be used to access large struct fields, the problem is creating the struct on the heap without first blowing up the stack.

@LoganDark
Copy link
Author

the problem is creating the struct on the heap without first blowing up the stack.

You cannot create a reference to uninitialized memory, that is undefined behavior. So you have to initialize the struct on the heap without creating a reference. In order to do this, to initialize memory, you have to write things into it. In order to write things into it, you need to know where the fields are that you're writing...

@Diggsey
Copy link
Owner

Diggsey commented Nov 16, 2021

I see. Depending on the nature of your struct, there may be other ways to initialize it. For example, if it consists entirely of fields for which zero is a valid bit pattern, then you can initialize the memory with zeros, and then create valid references to fields within it.

The stack overflow is a problem with the underlying memoffset crate, see Gilnaa/memoffset#49 so it's not something I can fix here.

Also, there's actually no practical way to make this work without causing UB. Determining the offset requires a non-dangling pointer to the struct, and if we can't create it on the stack, then the only other option would be to allocate it on the heap, which means it wouldn't work without alloc, and it would be pretty bad performance wise.

@LoganDark
Copy link
Author

if it consists entirely of fields for which zero is a valid bit pattern, then you can initialize the memory with zeros

That's actually what I needed! This works:

			let allocation = NonNull::new(alloc(Layout::new::<Self>()) as *mut Self)
				.expect("failed to allocate space");
			write_bytes(allocation.as_ptr(), 0, 1);
			Box::from_raw(allocation.as_ptr())

The stack overflow is a problem with the underlying memoffset crate, see Gilnaa/memoffset#49 so it's not something I can fix here.

Closing because it's an upstream issue then. Thanks!

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