3

I'm trying to find a way to catch a programmer error in the argument for malloc in an automated code tester.

For example:

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

This, of course, compiles without any problems. The thing is that struct Pepe has another struct of the same size inside it, therefore no problem appears during execution (nor with free).

The correct code should be:

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

Can we get a warning or something to catch this problem?

I tried -Wall and -Wextra but there was no warning.

12
  • valgrind will catch the subsequent write outside of allocated memory (if the structure happens to be larger than a pointer), among other subtle problems such as memory leaks Commented Feb 19, 2020 at 15:08
  • 4
    @leandrom You can use the following declaration struct Pepe* p = malloc(sizeof(*p)); to prevent the error. Commented Feb 19, 2020 at 15:08
  • 8
    A common ideom is to use struct foo *x = malloc (sizeof *x);; This will not warn you, but avoids the error altogether. Commented Feb 19, 2020 at 15:08
  • 1
    @ikegami struct happens to be EXACTLY same size as the pointer, no valgrind errors And yes, I know how to correctly declare, it's for doing automatic tests of code WITHOUT reading them ;) Commented Feb 19, 2020 at 15:10
  • 1
    I'd look at a static analysis package such as PC-lint . See gimpel.com/checks.html Commented Feb 19, 2020 at 15:50

4 Answers 4

4

You can use the clang static analyzer for that. Consider the following (buggy) code:

#include <stdlib.h>

struct foo {
    int a,b;
};

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

    free(bar);
}

Now you can invoke the clang static analyzer:

$ scan-build clang src.c

and get the following warning:

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.

The clang static analyzer is bundled with many linux distributions in the package clang-tools. The homepage can be found here

Sign up to request clarification or add additional context in comments.

1 Comment

This is good. I hadn't even thought about scan-build (although it seems to invoke GCC instead of Clang).
2

You can't really resolve the warning this way if you're naming the types.

An easier solution would be to use the variable to find its size. This also alleviates any possible issues with the type of the variable changing:

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

Now if I make p an int *...

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

it still works!

If you want to do it at execution time, you can build your code with the -fsanitize=address flag (assuming GCC or Clang) or you can use the Valgrind tool.

4 Comments

Thanks for the answer, btw you changed pretty much my post.... I tried to make clear that the idea is to TEST automatically other's people code without reading it (as i know how to use malloc correctly). So it looks like a typo but in reality they are making the mistake there. You see? So not really looking for a workaround but a way to catch it "compiling/execution" time if possible :)
@leandrom I made another edit that says "programmer error", but even so there's no way to do it without changing style or a memory checker like Valgrind or -fsanitize=address.
Aside: () not required after operator sizeof of an object. Could simplify to p = malloc(sizeof *p);
@chux-ReinstateMonica No. I like sizeof().
1

Don't know of any warning or so, but you can use a macro to get around the problem

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

Use it like this:

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

1 Comment

A macro!? Are you sure about this? What about maintainability?
1

The issue is that both statements are very much correct with 'c' and there is no way of catching it in the language. The malloc is just a function which the program calls in order to allocate some amount of memory. Compiler does not know anything about it, does not check and does not care. The only way around it is to use a good programming style, as mentioned in other replies of use a different programming language with build in memory management, e.g. java, c#, ...

However, there is a bunch of free and commercial static and dynamic linting tools (e.g., purify, cppcheck, clang static analyzer, ...) available for 'c' and 'c++'. Maybe you need to investigate them and use as a part of the build methodology. They should be able to catch those issues. And, as it was mentioned, valgrind is a free dynamic checker.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.