Я заново изучаю C и использую splint
для проверки исходного кода.
Я пытаюсь сделать следующее:
- создать структуру с помощью функции "конструктор"
- уничтожить структуру с помощью функции «деструктор», которая освобождает память структуры.
Однако, когда я тестирую свой код с помощью splint, он выдает предупреждения, связанные с временным хранилищем в деструкторе, и утечкой памяти после вызова деструктора.
Мне интересно (а) правильно ли шина говорит об утечке памяти в моем коде (я думаю, что это не так), и (б) что мне нужно сделать, либо исправить мой код, либо заставить шину понять, что я делаю.
В любом случае, вот код:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
// define the structure
struct Boring {
int amount;
};
// the creator
static struct Boring *Boring_create(int amount) {
struct Boring *really = malloc(sizeof(struct Boring));
assert(really != NULL);
really->amount=amount;
return really;
}
// the destroyer
static void Boring_destroy(struct Boring *really) {
assert( really != NULL );
// free the memory of the Boring structure
free(really);
}
int main( /*@unused@*/ int argc, /*@unused@*/ char *argv[]) {
int amount = 5;
struct Boring *tv = Boring_create(amount);
printf("The TV is boring level %d\n",tv->amount);
// destroy the tv!
Boring_destroy(tv);
printf("The TV is now boring level %d\n",tv->amount);
return 0;
}
/* Output */
/*
* $> ./destroytv
* The TV is boring level 5
* The TV is now boring level -538976289 (or 0 depending on OS/compiler)
*/
Код компилируется и отлично работает с gcc.
Однако, когда я использую шину для проверки, шина выдает следующие предупреждения:
$> splint boringtv.c
destroytv.c: (in function Boring_destroy)
destroytv.c: Implicitly temp storage really passed as only param: free (really)
Temp storage (associated with a formal parameter) is transferred to a new non-temporary reference. The storage may be released or new aliases crated. (Use -temptrans to inhibit warning)
destroytv.c: (in function main)
destroytv.c: Fresh storage tv not released before return
A memory leak has been detcted. Storage allocated locally is not released before the last reference to it is lost (use -mustfreefresh to inhibit warning)
Fresh storage tv created
Первое предупреждение, чем больше я об этом думаю, тем меньше понимаю. Но я не прочитал достаточно руководства, чтобы оправдать правильный вопрос об этом.
Второе предупреждение, про утечку памяти, похоже сплинт просто не понимает, что память освобождается в другом месте, что мне кажется странным. Предупреждение исчезнет, если я просто вызову free()
в пределах main
.
Заранее спасибо за помощь. Пожалуйста, дайте мне знать, если будут полезны дополнительные сведения, такие как номера строк для предупреждений.
printf("The TV is now boring level %d\n",tv->amount)
, верно? - person WhozCraig   schedule 26.06.2015assert
создает в вашем деструкторе ветку, которую splint может не понять полностью. Что произойдет, если вы прокомментируете это? - person Useless   schedule 26.06.2015splint
немного заржавел, но я вижу, что вы не аннотировали функциюBoring_destroy()
, чтобы указать, что она получает исключительное право собственности на свой аргумент, что она должна сделать, чтобы безопасно уничтожить его. Если вы добавите такую аннотацию, тоsplint
должен будет жаловаться на ваше разыменованиеtv
вprintf()
в концеmain()
, что является настоящей ошибкой. - person John Bollinger   schedule 26.06.2015assert()
для выполнения любого теста, без которого вы не хотите обойтись. Если утверждение когда-либо терпит неудачу, это должно быть признаком того, что программа неправильна, а не просто тем, что программа неудачна. Утверждение вBoring_destroy()
может соответствовать этим критериям, а утверждение вBoring_create()
— нет. - person John Bollinger   schedule 26.06.2015/*@only@*/
). Я добавлю правильный ответ. Дляassert
интересно. Я следовал учебнику Learn C the Hard Way, который использует его послеmalloc
и в деструкторе. Может быть, он просто пытался представить концепцию, а. - person hilcharge   schedule 27.06.2015