0

A part of my main contains

int* p = NULL;
p = malloc(sizof(int)*10); 
p = realloc(p, sizeof(int) * 5);
free(p);

Is there any way to find out if, after reallocation, the pointer p points to a memory block of size 20 bytes and not 40 bytes anymore?

The ideal would be to have a function that takes an address of memory as argument and tells if it's allocated or free. Is there such a function?

Another idea would be to check the size before and after the realloc() of the allocated memory. But I don't see how sizeof() could help, because how would I identify the block of memory, sizeof() sends the size of variables and not the size of a block of memory. sizeof(p) will give me 8 bytes, since p is a pointer and sizeof(*p) is 4, since p points to an integer.

Maybe there is a special use of sizeof() or some another function?

Read more if you want to know why I ask...

If I initialize my p to hold/point to an array

for (int i = 0; i < 3 ; i++){
   p[i] = i;
}

I want now p to hold only {0,1,2} so I want to reallocate p from sizeof(int)* 5 to sizeof(int)*3.

But let's say I don't really know if p should be reallocated, the memory block is 20 bytes, but maybe it's already 12 bytes, and realloc() is not needed. I know I can run realloc() either way and it won't hurt, so maybe it's not really a good reason for this question. But in a longer code it's easy to lose track of the amount of allocated memory.

Any help will be much appreciated.

PS: if no one answers I will have to get satisfaction from valgrind sending 0 errors.

After all, if something is wrong, for example writing in 21st, 22nd, 23rd and 24th bytes of memory (ex: p[4] = 7) of a block of 20 bytes (because p = realloc(p, sizeof(int) * 5)) valgrind sends errors of type "invalid write of size 4", but to get that I need to write in this memory. This method of verification makes me want to get errors, because if I can accurately predict an error then I know the actual size of the allocated memory.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • 5
    It's up to you to keep track of the size of the allocated memory at all times. If you don't know how many entries it really has then how can you even access it safely regardless of whether you want/need to ever `realloc` it? And no, there is no portable way to get the size of the allocated memory just from the pointer. – kaylum Nov 29 '21 at 09:02
  • Hi, kaylum. "How can I even access it safely ? " Well exacly, I can not, that's why I ask. Regardless of whether you want/need to ever realloc it, that's a good point. Thanks for the answer, I will just have to keep track of it. Maybe I will get to know some better methods of verification in the future. – Malwina Nov 29 '21 at 09:09
  • 3
    `realloc()` returns a valid pointer only if the allocation took place. If not, you'll receive a NULL pointer. Whether the old block was just shrunk or a different block was assigned, can be determined if you compare the old and the new value. – the busybee Nov 29 '21 at 09:09
  • 4
    `to get that I need to write in this memory. This method of verification makes me want to get errors` Why would you _want_ to verify that? If you do `malloc(20)` and it succeeds, you _know_ that you have 20 bytes, there's no point to verify it. – KamilCuk Nov 29 '21 at 09:11
  • 2
    It makes no sense to test system functions, except you doubt their implementation. But in that case you're quite lost. Read the documentation of the allocation functions, and then test _your_ code. – the busybee Nov 29 '21 at 09:12
  • 1
    *"Well exacly, I can not"*. Well you know enough about the size immediately after the `malloc/relloc` to be able to store the size after that. That's what I meant. Either it fails in which case no allocation was done or it succeeds in which case you know the size is at least what you asked it for. After that it is up to you to track that size. Asking to get the size from the pointer after that is not sensible. – kaylum Nov 29 '21 at 09:12
  • 1
    "But in a longer code it's easy to lose track of the amount of allocated memory." That's why larger projects use program design. It sounds like you should create a module treating this array as an "ADT" and let that module handle the allocation scheme, including keeping track of the size used. Which in turn is nothing new; most container classes and string libs etc in C do such things. – Lundin Nov 29 '21 at 09:23
  • 1
    @thebusybee Technically, according to the rules of the C standard, if the old and new pointer values are both non-null, you are not allowed to use the old pointer value in any expression because its value becomes indeterminate (C11 6.2.4p2), so you cannot compare the old and new pointers for equality in that case. – Ian Abbott Nov 29 '21 at 10:48
  • @IanAbbott By the letter this is mostly correct, using such a pointer is listed as UB with a reference to §7.22.3: "_[...] if the space has been deallocated by a call to the free or realloc function, [...] the behavior is undefined_" This reveals another vagueness of the standard. By the cited finding, "usage" means handing that pointer to `free()` or `realloc()`. -- A comparison is a completely different beast, and I see no problem, because it would mean that copying such a pointer could already trigger an exception. This is surely not meant. – the busybee Nov 29 '21 at 11:11
  • @thebusybee *This is surely not meant* Oh? You're able to deduce the limitations of every possible implementation of the C language? *A comparison is a completely different beast* Indeed it is. [What you describe is also undefined behavior](https://port70.net/~nsz/c/c11/n1570.html#6.5.8p5) "... In all other cases, the behavior is undefined." If two pointers don't refer in some way to the same object, comparing those pointers is undefined behavior. – Andrew Henle Nov 29 '21 at 11:15
  • (cont) And such a comparison is [invalid in another way, too](https://port70.net/~nsz/c/c11/n1570.html#6.2.4p2): "The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime." And *By the letter this is mostly correct*?!?! Ummm, so it's **incorrect** then? Because that's what "mostly correct" really means: "incorrect". Which is a really bad place to be for devices that literally do billions of operations per second. Only one operations needs to go bad for the entire result to be invalidated. – Andrew Henle Nov 29 '21 at 11:23
  • @AndrewHenle Correct, I did not dive deep enough. Anyway, UB is not "not allowed". – the busybee Nov 29 '21 at 11:23
  • So you tell your management that your code contains UB, and that means it could literally do anything and no result can ever truly be totally relied upon, but they should trust you that such a failure will never happen? On any platform they may port the code you write to in the future? Go on: go tell your bosses you deliberately ignore undefined behavior in your code and they can trust you that it's really OK because you know more than the authors of the C standard and all the compiler developers for any and all compilers that will ever be used to compile your code. – Andrew Henle Nov 29 '21 at 11:27

2 Answers2

2

There is no portable way of checking it.

You need to keep the size information yourself.

typedef struct String
{
    size_t size;
    int data[];
}data_type;


data_type *allocate(data_type *dt, size_t size)
{
    if(!dt || dt -> size != size)
    {
        dt = realloc(dt, sizeof(*dt) + size * sizeof(dt -> data[0]));
        if(dt)
        {
            dt -> size = size;
        }
    }
    return dt;
}

Usage is the same as realloc. If you pass NULL pointer it will allocate the the stricture and space for data. If you change the size, save the result in the temporary pointer and check if allocation did not fail. If the requested size is the same as the actual allocated space it will do nothing (as reallocation is not needed)

0___________
  • 60,014
  • 4
  • 34
  • 74
2

Is there any way to find out if, after reallocation, the pointer p points to a memory block of size 20 bytes and not 40 bytes anymore?

No

This method of verification makes me want to get errors, because if I can accurately predict an error then I know the actual size of the allocated memory.

Use -fsanitize=address for both compiler and linker. Read more here: https://stackoverflow.com/a/40215639/6699433

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
klutt
  • 30,332
  • 17
  • 55
  • 95