-
Notifications
You must be signed in to change notification settings - Fork 75
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
Improve multi-threaded valid-memcleanup
#1246
Improve multi-threaded valid-memcleanup
#1246
Conversation
How can |
Fair point, thanks for the heads up! I think we could just keep track of allocated and freed memory as part of the global invariant in that case. That way we should be able to check for memory leaks at thread return/exit points. |
Does not suffice to just keep track locally? If one of the functions that just terminates execution altogether, we warn. Otherwise, each thread checks for itself if it did a cleanup. |
The issue that when collecting the memory that is freed in the global invariant, this would be memory that may be freed: If one were to side-effect memory that would be freed whenever our overapproximation reaches a program point that calls Therefore, the set of allocated/freed memory should still be tracked in the local state, like in the single-threaded case. |
So, I now tried again by removing the global state completely and using the local state instead:
Note: for some reason, the check for the points-to set cardinality being one breaks the multi-threaded test cases and it fails to detect P.S.: Thanks for your tips in the previous comments :) |
due to `memcleanup` or `memtrack` violations
I added the two Goblint options Since the |
Where exactly is this check missing and what does it mean if we don't check for singleton points-to there? Also, I'm a bit puzzled how this can work with just local state (except for the global boolean now). That essentially means, leaks can be checked by knowing nothing about any other threads. But how is that possible without even observing what other threads do? |
But we don't check that here at all because threads don't observe each other at all. For example, here we find no memory leak because the leaky thread never terminates: //PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak
#include <stdlib.h>
#include <pthread.h>
int *m1;
void *f1(void *arg) {
m1 = malloc(sizeof(int));
while (1);
}
int main(int argc, char const *argv[]) {
pthread_t t1;
pthread_create(&t1, NULL, f1, NULL);
return 0; //NOWARN
} |
I don't think this is a memory leak (or at least not in the sense used in sv-comp). The program will not terminate as |
It terminates immediately if you compile and run it: https://godbolt.org/z/3sjshTj3h. It's not specific to the main thread returning even. Any other thread may call |
Crap, you're right of course. We take care of calls to |
I got confused with the threading model of the JVM. |
We should add an is-single-thread query for returning from main then, that should make it sound again. |
I will have a look at this. |
…aded. If other threads are not joined, they may be killed by the main thread returning. This will possibly leak memory.
… thread_joins to other test cases.
I added a check that when the main thread reaches its return, it is definitely single-threaded in case ever any memory was allocated. I wondered whether a
I.e., if the |
The analysis now requires the |
…sis from params as it is not needed.
The analysis is currently unsound on this test case, as Goblint thinks that the program is single-threaded at the end of //PARAM: --set ana.malloc.unique_address_count 1 --set ana.activated[+] memLeak --set ana.activated[+] thread
#include <stdlib.h>
#include <pthread.h>
int *m1;
void *f2(void *arg) {
m1 = malloc(sizeof(int));
while (1);
return NULL;
}
void *f1(void *arg) {
pthread_t t2;
pthread_create(&t2, NULL, f2, NULL);
pthread_exit(NULL);
return NULL;
}
int main(int argc, char const *argv[]) {
pthread_t t1;
pthread_create(&t1, NULL, f1, NULL);
pthread_join(t1, NULL);
return 0; // WARN
} So the handling of |
Handling a |
I looked at it, and this seems to indeed be what we want here. |
tests/regression/76-memleak/08-invalid-memcleanup-multi-threaded.c
Outdated
Show resolved
Hide resolved
Co-authored-by: Simmo Saan <simmo.saan@gmail.com>
…return before side-effecting.
…d returns and normal returns of a thread.
I think we can now merge this into master as well? Wdyt @sim642? |
CHANGES: Functionally equivalent to Goblint in SV-COMP 2024. * Add termination analysis for loops (goblint/analyzer#1093). * Add memory out-of-bounds analysis (goblint/analyzer#1094, goblint/analyzer#1197). * Add memory leak analysis (goblint/analyzer#1127, goblint/analyzer#1241, goblint/analyzer#1246). * Add SV-COMP `termination`, `valid-memsafety` and `valid-memcleanup` properties support (goblint/analyzer#1220, goblint/analyzer#1228, goblint/analyzer#1201, goblint/analyzer#1199, goblint/analyzer#1259, goblint/analyzer#1262). * Add YAML witness version 2.0 support (goblint/analyzer#1238, goblint/analyzer#1240, goblint/analyzer#1217, goblint/analyzer#1226, goblint/analyzer#1225, goblint/analyzer#1248). * Add final warnings about unsound results (goblint/analyzer#1190, goblint/analyzer#1191). * Add many library function specifications (goblint/analyzer#1167, goblint/analyzer#1174, goblint/analyzer#1203, goblint/analyzer#1205, goblint/analyzer#1212, goblint/analyzer#1220, goblint/analyzer#1239, goblint/analyzer#1242, goblint/analyzer#1244, goblint/analyzer#1254, goblint/analyzer#1269). * Adapt automatic configuration tuning (goblint/analyzer#912, goblint/analyzer#921, goblint/analyzer#987, goblint/analyzer#1168, goblint/analyzer#1214, goblint/analyzer#1234).
CHANGES: Functionally equivalent to Goblint in SV-COMP 2024. * Add termination analysis for loops (goblint/analyzer#1093). * Add memory out-of-bounds analysis (goblint/analyzer#1094, goblint/analyzer#1197). * Add memory leak analysis (goblint/analyzer#1127, goblint/analyzer#1241, goblint/analyzer#1246). * Add SV-COMP `termination`, `valid-memsafety` and `valid-memcleanup` properties support (goblint/analyzer#1220, goblint/analyzer#1228, goblint/analyzer#1201, goblint/analyzer#1199, goblint/analyzer#1259, goblint/analyzer#1262). * Add YAML witness version 2.0 support (goblint/analyzer#1238, goblint/analyzer#1240, goblint/analyzer#1217, goblint/analyzer#1226, goblint/analyzer#1225, goblint/analyzer#1248). * Add final warnings about unsound results (goblint/analyzer#1190, goblint/analyzer#1191). * Add many library function specifications (goblint/analyzer#1167, goblint/analyzer#1174, goblint/analyzer#1203, goblint/analyzer#1205, goblint/analyzer#1212, goblint/analyzer#1220, goblint/analyzer#1239, goblint/analyzer#1242, goblint/analyzer#1244, goblint/analyzer#1254, goblint/analyzer#1269). * Adapt automatic configuration tuning (goblint/analyzer#912, goblint/analyzer#921, goblint/analyzer#987, goblint/analyzer#1168, goblint/analyzer#1214, goblint/analyzer#1234).
This PR is an attempt to improve precision for
valid-memcleanup
in multi-threaded programsMain idea:
*alloc()
call:free()
call:Test case
76/08
is still not working as expected, but I wanted to open the PR, so that you can also take a look at it