0

I am trying to allocate 10000 page-tables but unable to compile. I am getting the following error.

error: invalid conversion from 'void*' to 'char (*)[(<anonymous> + 1)]' [-fpermissive]
     char (*my_memory)[sysconf(_SC_PAGESIZE)] = mmap(NULL,PAGE_SIZE * (100000 + OVERSIZE),PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS,-1,0);

My code as below.

int main(int argc, char **argv) {
    unsigned long physical_addr;
    uint8_t *buf;
    unsigned long virtual_addr;
    char (*my_memory)[sysconf(_SC_PAGESIZE)] = mmap(NULL,PAGE_SIZE * (100000 + OVERSIZE),PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS,-1,0);
    int i;
    for (i = 0; i * sizeof(*my_memory) < 10000; i++) {
        my_memory[i][0] = 1;
    }
}

Not sure how to solve this. Please help.

Jim Stewart
  • 16,964
  • 5
  • 69
  • 89
  • 1
    You can't assign an array... – Eugene Sh. Nov 18 '16 at 18:32
  • 1
    `my_memory` should be a [pointer to array](http://cdecl.ridiculousfish.com/?q=char+%28*my_memory%29%5B4096%5D) – Kninnug Nov 18 '16 at 18:34
  • 6
    Are you using a C++ compiler by chance? – aschepler Nov 18 '16 at 18:37
  • @Kninnug Right.. my bad. – Eugene Sh. Nov 18 '16 at 18:41
  • 2
    `char (*my_memory)[sysconf()] = mmap(....);` should work. Dummy test: https://ideone.com/0QBeSx. And this answer: http://stackoverflow.com/a/11454408/669576. – 001 Nov 18 '16 at 18:46
  • does it work with an explicit cast? – Amin Negm-Awad Nov 18 '16 at 18:51
  • a couple of things: 1) do you have enough memory after deductions for the OS and other programs and your program (between real RAM and the SWAP area on the disk to hold 10000 page sized memory (when a page size is 4096 bytes, that is 409.600,000 bytes? 2) If your running under windows, there is only about 1meg of memory available for the stack and your trying declare a table of ~409meg pointers to char which will consume 409meg * sizeof( char * ) bytes. 3) the call to `mmap()` only returns a single pointer, so suggest something like: `char *myMemory = mmap(....)`; – user3629249 Nov 19 '16 at 08:29
  • I understand the program when allocated will approximately use 40mb of memory. I was able to execute it successfully without using single indexing so believe I do have enough memory. But I was wondering if it was possible to do it with double indexing. I am using Linux by the way. – Ashwin Gopalakrishnan Nov 19 '16 at 16:03
  • @AshwinGopalakrishnan So: (1) Are you using a C++ compiler? (2) Does it work with an explicit cast? Please [edit] your question and clarify these points. – anatolyg Nov 21 '16 at 07:39
  • yes. I am using a c++ compiler. I figured out a solution using single indexing. Thanks everyone. – Ashwin Gopalakrishnan Nov 21 '16 at 20:39

2 Answers2

1

You can't assign to an array from a pointer. If you make my_pointer a bare pointer, this assignment will work, but you'll lose the ability to do the double-indexing that you're doing in the code you've posted; instead, you'll need to come up with an indexing scheme that allows you to use a 1D-array instead. Your code would then look like:

int main(int argc, char **argv) {
    unsigned long physical_addr;
    uint8_t *buf;
    unsigned long virtual_addr;
    char *my_memory = mmap(NULL,PAGE_SIZE * (100000 + OVERSIZE),PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS,-1,0);
    int i;
    for (i = 0; i < 10000; i++) {
        my_memory[PAGE_SIZE * i] = 1;
    }
}

(Note that I'm sort of inferring what that last loop was intended to do; my interpretation was that you wanted it to set the first byte of every "page" to 1)

Haldean Brown
  • 12,411
  • 5
  • 43
  • 58
  • 1
    As @Kninnug have already corrected me, it is not an array but a pointer to array.. – Eugene Sh. Nov 18 '16 at 18:44
  • 1
    OP clearly wants double-indexing. Replacing it by single, calculated indexing works, but I think you can do better. – anatolyg Nov 18 '16 at 18:48
  • Thank you for your reply. I was actually looking for a solution which uses double indexing. – Ashwin Gopalakrishnan Nov 18 '16 at 23:09
  • @AshwinGopalakrishnan You might want to answer some questions that people asked you in the comments below your question. If you want to get a solution better than this one, you should answer these questions. – anatolyg Nov 19 '16 at 15:25
0

You should use casting to a proper type, since you are actually using the C++ language.

In C, this code would work:

char (*my_memory)[sysconf(_SC_PAGESIZE)] = mmap(...);

Here my_memory is a pointer to an array of chars. C has built-in conversion from void* to any pointer, so the code is legal in C, and does what you want.

If you want to make it work in C++, you should add a cast.

The type of my_memory is char (*)[sysconf(_SC_PAGESIZE)]. So the casting will look like this:

char (*my_memory)[sysconf(_SC_PAGESIZE)] = static_cast<char (*)[sysconf(_SC_PAGESIZE)]>(mmap(...));

or, in a less verbose manner:

auto my_memory = static_cast<char (*)[sysconf(_SC_PAGESIZE)]>(mmap(...));

or, if you want to make the code as short as possible (less readable):

auto my_memory = (char (*)[sysconf(_SC_PAGESIZE)])mmap(...);

Some people prefer to have a typedef for complex types like pointers to arrays. If you want to go this route, here is the syntax:

using my_array_ptr_type = char (*)[sysconf(_SC_PAGESIZE)];
auto my_memory = static_cast<my_array_ptr_type>(mmap(...));
anatolyg
  • 26,506
  • 9
  • 60
  • 134