1

I'm trying to write simple memory manager. I have a test file with following asserts:

VA page_1 = NULL;
void* pBuffer_1 = "0123";
size_t szBuffer_1 = sizeof("0123");

//right execution
assert(_write(page_1, pBuffer_1, szBuffer_1) == 0);

//assert pointer value
assert(*page_1 == pBuffer_1);

and _write() function:

int _write(VA ptr, void* pBuffer, size_t szBuffer)
{
    if (pBuffer == NULL) return -1;
    if (szBuffer < 1) return -1;
    if (szBuffer > MMEM.page_size - MMEM.table[MMEM.pages_filled].filled_bytes)
        return -2;

    memcpy(&MMEM.table[MMEM.pages_filled].data, pBuffer, szBuffer);
    ptr = &MMEM.table[MMEM.pages_filled];

    if (ptr == NULL) return 1;

    MMEM.table[MMEM.pages_filled].filled_bytes += szBuffer;
    MMEM.pages_filled++;

    return 0;
}

The problem is the second assert() don't pass because of page_1 == NULL. In debug before ptr = &MMEM.table[MMEM.pages_filled]; ptr is NULL and after ptr 0x00fe5568 '0123'. Why inside thу function it works but out of it my pointer is NULL?

Pavel Antspovich
  • 1,111
  • 1
  • 11
  • 27
  • 1
    You pass `page_1` **by value** to `_write`, so your function argument `ptr` is a copy of `page_1`. Your assignment in `_write` modifies the local copy but does not have any effect on the value of `page_1`. You can either change the signature of your function to `int _write(VA *ptr, void* pBuffer, size_t szBuffer)`, assign it as `*ptr = &MMEM.table[MMEM.pages_filled];` and call `_write(&page_1, pBuffer_1, szBuffer_1)` or use the return value instead of a function argument to deliver the pointer value to the calling function. – Bodo Nov 07 '19 at 09:20
  • 1
    You should not use `assert` to check the result of a function call. `assert` is to check for preconditions, a failed check indicates a programming error and aborts the program immediately. Better use something like `if (_write(page_1, pBuffer_1, szBuffer_1) != 0) { fprintf(stderr, "_write failed ...\n"); exit(1); }`. – Bodo Nov 07 '19 at 09:23
  • @Bodo, thanks a lot! You can write the answer and I'll mark it as helpful – Pavel Antspovich Nov 07 '19 at 09:24
  • Please decide if you want to use `C` or `C++` and remove the other tag. There are already answers similar to my comment. – Bodo Nov 07 '19 at 09:26

2 Answers2

3

The function deals with a copy of the pointer page_1. Function parameters are its local variables. So any changes of the copy within the function do not influence on the value of the original pointer.

If you want to change the original value of the pointer within the function then pass it by reference through a pointer to the pointer. I assume that the code is a C code.

int _write(VA *ptr, void* pBuffer, size_t szBuffer);

Otherwise declare the parameter as having a referenced type.

int _write(VA &ptr, void* pBuffer, size_t szBuffer);
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I have a technical task to use ```int _write(VA ptr, void* pBuffer, size_t szBuffer)``` signature. How can I use it? – Pavel Antspovich Nov 07 '19 at 09:20
  • @PavelAntspovich For starters the code is just awful. So I do not think you should keep it unmodified. Without changing the function signature you will be unable to do your task. If it is a C++ code then declare the parameter as a referenced type as for example Va &ptr. – Vlad from Moscow Nov 07 '19 at 09:21
2

try this:

assert(_write(page_1, pBuffer_1, szBuffer_1) == 0);
//...
int _write(VA& ptr, void* pBuffer, size_t szBuffer);  //NOTICE the & on ptr.

you are passing the value of page_1 by value. all the changes in the function will be a copy of the original page_1.

acegs
  • 2,621
  • 1
  • 22
  • 31