Как я могу поймать ошибку программиста с mallo c? - PullRequest
3 голосов
/ 19 февраля 2020

Я пытаюсь найти способ отловить ошибку программиста в аргументе для malloc в автоматическом тестере кода.

Например:

struct Pepe* p = malloc(sizeof(struct Pepe*));

Это, из Конечно, компилируется без проблем. Дело в том, что struct Pepe имеет внутри другую структуру того же размера, поэтому во время выполнения не возникает проблем (ни с free).

Правильный код должен быть:

struct Pepe* p = malloc(sizeof(struct Pepe));

Можем ли мы получить предупреждение или что-то еще, чтобы решить эту проблему?

Я пробовал -Wall и -Wextra, но предупреждения не было.

Ответы [ 4 ]

4 голосов
/ 19 февраля 2020

Для этого вы можете использовать анализатор clang stati c. Рассмотрим следующий (ошибочный) код:

#include <stdlib.h>

struct foo {
    int a,b;
};

int main (void) {
    struct foo *bar = malloc(sizeof(struct foo *));

    free(bar);
}

Теперь вы можете вызвать анализатор clang stati c:

$ scan-build clang src.c

и получить следующее предупреждение:

src.c:10:20: warning: Result of 'malloc' is converted to a pointer of type 'struct foo', which is incompatible with sizeof operand type 'struct foo *'
        struct foo *bar = malloc(sizeof(struct foo *));
        ~~~~~~~~~~~~      ^~~~~~ ~~~~~~~~~~~~~~~~~~~~
1 warning generated.
scan-build: 1 bug found.

Анализатор clang stati c в комплекте со многими linux дистрибутивами в пакете clang-tools. Домашнюю страницу можно найти здесь

2 голосов
/ 19 февраля 2020

Вы действительно не можете разрешить предупреждение таким образом, если вы называете типы.

Более простым решением было бы использование переменной, чтобы найти ее размер. Это также устраняет любые возможные проблемы с типом изменяемой переменной:

struct Pepe *p = malloc(sizeof(*p));

Теперь, если я сделаю p int * ...

int *p = malloc(sizeof(*p));

, он все еще работает!

Если вы хотите сделать это во время выполнения, вы можете создать свой код с флагом -fsanitize=address (при условии G CC или Clang) или использовать инструмент Valgrind .

1 голос
/ 19 февраля 2020

Проблема заключается в том, что оба утверждения очень правильны с 'c', и нет возможности уловить их в языке. malloc - это просто функция, которую программа вызывает для выделения некоторого объема памяти. Компилятор ничего не знает об этом, не проверяет и не заботится. Единственный способ обойти это - использовать хороший стиль программирования, как упоминалось в других ответах об использовании другого языка программирования со встроенным управлением памятью, например java, c#, ...

Однако, Существует множество бесплатных и коммерческих инструментов stati c и dynamic c linting (например, очистить, cppcheck, clang stati c анализатор, ...), доступных для 'c' и "с ++". Возможно, вам нужно изучить их и использовать как часть методологии сборки. Они должны быть в состоянии уловить эти проблемы. И, как уже упоминалось, valgrind - это бесплатная динамическая c программа проверки.

1 голос
/ 19 февраля 2020

Не знаю ни одного предупреждения или около того, но вы можете использовать макрос, чтобы обойти проблему

#define ALLOC(p, n)  ((p) = malloc((n) * sizeof *(p)))

Используйте это так:

struct Pepe *p;
ALLOC(p, 1);
...