-2

I'm making a file whose job is specifically to keep track of how many blocks I currently have allocated, as I don't want any memory leaks.

size_t BLOCKS_CURRENTLY_ALLOCATED = 0;

/* Since variables can be allocated in lots of different ways,
malloc, calloc, realloc, etc don't allocate here. Just mark down
how many bytes of memory was used for this value. */
void allocate(const void const *val)
{
    BLOCKS_CURRENTLY_ALLOCATED += sizeof(*val);
}

/* Update the amount of blocks counter and free the pointer. */
void deallocate(const void const *val)
{
    // Edit: I think I meant to do `sizeof(val)` but I don't know if that works
    const size_t size = sizeof(*val);
    if (BLOCKS_CURRENTLY_ALLOCATED < size)
        exit(1); // Error, must have forgotten to report allocating.
    free(val);
    BLOCKS_CURRENTLY_ALLOCATED -= sizeof(size);
}

Is this code all legal? Am I able to use sizeof to get the amount of blocks that were allocated for an unknown data type pointer that was at some point allocated with malloc or calloc? What about calling free on a pointer whose data is const and pointer is const?

Hatefiend
  • 3,416
  • 6
  • 33
  • 74
  • 2
    `sizeof` s compile time. So how would `sizeof` now in runtime how many bytes are allocated for `*val`? – Paul Ogilvie Feb 24 '17 at 08:41
  • `sizeof(*val)` will return 1 if its a `char*` as it will point to first character which is 1 byte. Perhals I am mistaked but you would want to find the whole string size. – Tony Tannous Feb 24 '17 at 08:44
  • Can't it head to the memory location that `val` is stored at and then there `malloc` has stored a value of how many bytes exist in this block? If I did `int *x = malloc(sizeof(int) * 5);` then `void *p = x;`, wouldn't `printf("Amount of blocks: %zu\n", sizeof(p));` print `sizeof(int) * 5`? How is what I have any different? – Hatefiend Feb 24 '17 at 08:44
  • Are you getting any compilation error? I think you should because it is not allowed to deference a `void*` pointer – Avantika Saini Feb 24 '17 at 08:48
  • @Avantika Saini I have not attempted to run this as I am currently away from a PC. Am I not allowed to use `const` in combination with the `free` function? – Hatefiend Feb 24 '17 at 08:54
  • Here, you are trying to dereference a pointer `*val` which is of type `void*`. This is illegal in C. You can not dereference a void pointer without casting it to one of the data types like `char`, `int` etc – Avantika Saini Feb 24 '17 at 09:00
  • `sizeof(*val): error C2100: illegal indirection` on VC 2008. – Paul Ogilvie Feb 24 '17 at 09:00
  • Sorry sorry what I think I meant is to not de-reference and instead just attempt to get the `sizeof(void*)`. Does that work? – Hatefiend Feb 24 '17 at 09:03
  • `sizeof(void*) ` is fine. It is the size of a pointer. That size has nothing to do with its value nor what it might point to. – chux - Reinstate Monica Feb 24 '17 at 14:43
  • @chux I want to get the size of the block that `void*` points to – Hatefiend Feb 24 '17 at 19:00
  • @Hatefiend The value given to `void *ptr = *alloc(some_size)` needs to be retained by the code. It is not generally available by using `ptr`. – chux - Reinstate Monica Feb 24 '17 at 19:15
  • Consider not using `*alloc(), free(), etc.` directly, but make your own that, in turn, call the standard functions. Then your functions can keep track of allocation statistics. BTW, `void*` is not sufficient as a pinter to _any_ type. [ref](http://stackoverflow.com/a/42299077/2410359) – chux - Reinstate Monica Feb 24 '17 at 19:19

3 Answers3

4

Your code does not follow standard C.

You cannot use sizeof on a variable of type void. This is some sort of nonsense, non-standard extension. I would guess it gives size 1 or something meaningless like that. Even if it would be valid C, you cannot use sizeof to get the size of an unknown type like you think - C doesn't have any form of run-time type information.

In addition, you cannot pass a pointer of type const void* to a function expecting void*. C does not allow implicit pointer conversions that remove qualifiers.

Overall, you need a better compiler because there is no way this code should pass compilation.

As a side-note, const void const * is nonsense. You probably meant const void* const? The former makes as little sense as const const const const const void* although C allows it.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • I knew `void*` is the only way to simulate an unknown type, and I thought that functions like `malloc` store the `size_t` block size in the same block as the allocated variable. Thus, when I call `sizeof` on a `(void*)` then it would inform me the `size_t` block size ASSUMING this `void*` was once dynamically allocated on the heap. Based on what you say, that's clearly impossible? – Hatefiend Feb 24 '17 at 09:02
  • @Hatefiend One way to design the heap allocaiton is indeed to store the size together with the data. Your assumptions about `sizeof` are wrong, it is a compile-time operator which only knows how to give you the size of _types_. It knows nothing about data allocation on your application-level. You'd have to design the whole heap allocation yourself if you want to access that kind of information. Which is of course fully possible. – Lundin Feb 24 '17 at 09:21
  • 1
    @Lundin With VLA:s, it's not strictly compile-time any more. Still, well put. – unwind Feb 24 '17 at 10:34
0

The approach is actually wrong. What you can do is (let's assume you're using native C memory management API), to redefine all memory operation functions (like malloc/realloc/free) where:

  1. You add to each allocated block a header where you store the size of the allocated memory. This header is at the beginning of the mem block.
  2. You return to the client the pointer to the first byte after the header.
  3. Upon reallocation/freeing you deal with the entire block. And also you can access the header any time as you know its beginning will be at some bytes (as per your definition) lower than the pointer which is in operation by the client code.

In the same way you can add additional info with some pattern before and after each allocated mem block and later test them whether they are not corrupted in the meantime.

dmi
  • 1,424
  • 1
  • 9
  • 9
  • Just so I understand, you're saying that I should make five functions, `calloc`, `realloc`, `malloc`, `alloc`, and `free` all with the same parameters as the default C functions. Inside the C functions, I should add to the counter and then perform the regular C functions, then return the allocated pointer just like `malloc` or `calloc` would? Why is my approach bad? Will it not work? – Hatefiend Feb 24 '17 at 08:52
  • Your understanding is correct - you need to redefine system memory operations. How this can be done - depends on the OS. Why your approach is not correct - is written in other answers. From your code I understand, that besides the missuse of sizeof, you are based on an assumtion that the size info is in the memory block somewhere. And you're trying to read it somehow. However, this is implementation dependent, and you should (shall) not follow this approach. – dmi Feb 24 '17 at 10:01
-2

this is an error!

void* a; sizeof(a); if vaild because the size of every pointer is 4 bytes.

void* a; sizeof(*a); is not vaild because you can never know to what a void pointer pointing to so you can never know what is the size of it. it can be a char, an int, a pointer, .....

also, if you write void* ?=malloc(??) this command (sizeof(?)) will return 4. not ??.

Roy Avidan
  • 769
  • 8
  • 25
  • I'm trying to make a function that takes in a pointer and tells me how many blocks of memory it was allocated with. The amount should match the amount that I `malloc()`'ed it. For example: `int *x = malloc(sizeof(int) * 10);` `myFunction(x);` Inside `myFunction`, I want it to print `40` (or 80 if on 64 bit system) – Hatefiend Feb 24 '17 at 09:39
  • `sizeof` and `malloc` are not connected. i will add this to the answer. – Roy Avidan Feb 24 '17 at 09:50
  • Why do you think the size of a pointer is 4? It might be on some platforms, but it's implementation-defined, and certainly not the case everywhere. – Toby Speight Feb 24 '17 at 10:24