-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
returning a pointer to a local should be a compile error #5725
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
Comments
There has already been some work done on this (see |
Ah, I thought there might have been. I'll keep this open for explication's sake, though. Is the plan to disallow this at comptime as well? |
from zig weekly 2020/12/16
If the compiler can prove something statically that is an error, let's emit an error. For unused variables, let's reduce the surface:
How effectual will this be? If it's not a compile-speed killer and relatively straight forward, why not? Whether this is a warning or error, is a different question. On the subject of returning local pointers:
Against the first point, it doesn't matter if the function is called in all cases. We already allow bogus things in lazy functions that would blow up if ever compiled. This should not be a prerequisite for detecting errors. Against the third point, we could knowingly let local pointers escape with attribution: fn getEndOfStackPtr() *noderef const u8 { ... } which lets zig know and enforce that pointer can never be dereferenced. Thus it is possible to return but never deref. In the other case, if the compiler can prove escape, that needs to be an error. And again here, it doesn't matter if the compiler can detect 100% escapes. Any % is valuable. |
I made a mistake due to this and the program worked for many cases, until a test finally observed a "corrupted" value and it took me several hours to find out this was the problem. In my case the pointer was a little bit hidden behind a call like this: var buffer: [3]u8{0,0,0};
/// do stuff
return std.fmt.bufPrint(&buffer, "{d}", .{code}); This made me sad... a language that allows this without warnings cannot be used to write reliable code. Hope Zig can fix this. |
At least for C its not possible in a portable way: https://stackoverflow.com/a/16361335
This makes me suspect, that this should be part of tooling https://en.wikipedia.org/wiki/Dangling_pointer#Dangling_pointer_detection or static analysis with the ability to annotate intended program semantics (without static analysis can only help for simple cases or has significant runtime cost). |
I don't see why we cannot make returning a pointer to a local variable undefined behavior. If this behavior is desired then it can be made explicit with |
Has this been implemented? const std = @import("std");
fn get() *[10]u8 {
var data : [10]u8 = undefined;
var j: u8 = 0;
for (0..10) |i| {
data[i] = j + 65;
j += 1;
}
return &data;
}
pub fn main() !void {
const data = get();
std.debug.print("{s}\n", .{data});
} Compiles perfectly fine, but it of course broken. Comparable c code: #include <stdio.h>
int* get() {
int thing[10];
for (int i=0; i<10; i++) {
thing[i] = i + 65;
}
return thing;
}
int main() {
int* data = get();
printf("%s\n", data);
} Gives a warning: |
No, that's why the issue remains open. |
I don't think it's possible to catch at compile-time. Please see this issue for catching it at runtime: #23528 |
Uh oh!
There was an error while loading. Please reload this page.
Maybe duplicate, but I couldn't find it anywhere.
Consider the following code:
No problems here, copy elision (should) put
inst
in the right place. Now consider this alternative:Someone who doesn't know all the details of RLS might do this. Problem is,
frame
is now explicitly stack-allocated, in a frame which is invalidated as soon asinit
returns. This is comptime-detectable undefined behaviour. Zig should not compile this code.(There are reasons not to allow this at comptime either -- just look at the headache that is #5718 (comment). Also, breaking from blocks permits a similar problem.)
The text was updated successfully, but these errors were encountered: