If I reuse the same rpmtd for multiple headerGet() or rpmtdGetString() calls, would this cause a memory leak? #2492
-
I would like help determining if I am incorrectly using // Compile with:
// gcc -Wall -Wextra -Werror -Og -g -lrpm -lrpmio mre.c -o e
#include <stdlib.h>
#include <stdio.h>
#include <rpm/rpmdb.h>
#include <rpm/rpmlib.h>
#include <rpm/rpmts.h>
#include <rpm/rpmmacro.h>
const char* getString(Header h, rpmTag tag, struct rpmtd_s* td) {
if (headerGet(h, tag, td, HEADERGET_DEFAULT)) {
return rpmtdGetString(td);
}
return NULL;
}
int main() {
rpmts ts;
Header h;
rpmdbMatchIterator mi;
rpmReadConfigFiles(NULL, NULL);
ts = rpmtsCreate();
if (!ts) {
return 1;
}
mi = rpmtsInitIterator(ts, (rpmTag)RPMDBI_PACKAGES, NULL, 0);
if (!mi) {
rpmtsFree(ts);
return 1;
}
h = rpmdbNextIterator(mi);
if (h == NULL) {
return 1;
}
struct rpmtd_s td;
const char* s1 = getString(h, RPMTAG_NAME, &td);
if (s1 != NULL)
printf("Name: [%s]\n", s1);
const char* s2 = getString(h, RPMTAG_VERSION, &td);
if (s2 != NULL)
printf("Version: [%s]\n", s2);
// Note that I only free td once after using it twice
rpmtdFreeData(&td);
rpmdbFreeIterator(mi);
rpmtsFree(ts);
rpmFreeMacros(NULL);
rpmFreeRpmrc();
return 0;
} Since I only free the I am worried that there might be a memory leak since there is an If there is a memory leak in my code above, is the way to avoid a memory leak to use a separate |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
It's okay to reuse the same struct rpmtd_s for multiple calls, BUT each headerGet() needs to be paired with a rpmtdFreeData(), otherwise it will leak memory. The worse problem in the above is that string pointers you get this way turn to garbage on rpmdbNextIterator() - it will not matter for the above snippet but will likely come bite you once it grows into a larger program. HEADERGET_DEFAULT is a braindamaged mode which returns pointers into header memory for some data and allocated for others, unless you're very sure of what you're doing, HEADERGET_ALLOC is the right mode to use with headerGet(). If you only need non-array data from the header, you might as well save yourself some pain of awkward API's and just use headerGetAsString() to fetch the data converted into malloced string, plain and simple. For numeric data, headerGetNumber() is a similar shortcut. |
Beta Was this translation helpful? Give feedback.
It's okay to reuse the same struct rpmtd_s for multiple calls, BUT each headerGet() needs to be paired with a rpmtdFreeData(), otherwise it will leak memory. The worse problem in the above is that string pointers you get this way turn to garbage on rpmdbNextIterator() - it will not matter for the above snippet but will likely come bite you once it grows into a larger program.
HEADERGET_DEFAULT is a braindamaged mode which returns pointers into header memory for some data and allocated for others, unless you're very sure of what you're doing, HEADERGET_ALLOC is the right mode to use with headerGet().
If you only need non-array data from the header, you might as well save yourself some pain…