портирование c ++ с dev c ++ на visual c ++ - PullRequest
0 голосов
/ 09 апреля 2019

Я пытался перейти от кода dev c ++ к visual studio 2017, а затем мой код не работает, потому что он говорит expression must be a pointer to a complete object type Так что я пытался выяснить, что происходит, но я застрял на том, как его решить.

void print_function_instructions(void *func_ptr, size_t func_len) {
    for (unsigned char i = 0; i < func_len; i++) {
        unsigned char *instruction = (unsigned char*)func_ptr + i;
        printf("%p (%2u): %x\n", func_ptr + i, i, *instruction); # expression must be a pointer to a complete object type
    }
} 


int change_page_permissions_of_address(void *addr) {
    // Move the pointer to the page boundary
    int page_size = getpagesize();
    DWORD dwOldProtect;
    addr -= (unsigned uintptr_t)addr % page_size; #expression must be a pointer to a complete object type

    if (VirtualProtect(addr, page_size, PAGE_EXECUTE_READWRITE, &dwOldProtect) == -1) {
        return -1;
    }

    return 0;
}

Ответы [ 2 ]

3 голосов
/ 09 апреля 2019

Вы узнали плохую привычку от gcc (компилятор, наиболее часто используемый с Dev C ++). Несмотря на то, что он во многих отношениях хорошо соответствует стандарту C ++, в одном он не дает результатов. Согласно стандарту, вам не разрешается делать какие-либо арифметические действия с пустыми указателями.

Пустой указатель в основном предназначен для "держателя". Вы можете поместить указатель на любой тип объекта в указатель void, а позже вы можете получить его обратно - но вы не можете фактически делать какие-либо подобные указателю вещи (разыменование или арифметику указателя) с самим указателем void.

GCC терпит неудачу в этом отношении. Хотя он не позволит вам разыменовать пустой указатель, он позволит вам выполнить арифметику с пустым указателем. Когда вы это делаете, он обрабатывает его так, как если бы он был указателем на символ, поэтому, если вы увеличиваете или уменьшаете его, это происходит в единицах единицы.

Чтобы поддерживать арифметику, вы, вероятно, захотите создать указатель на (возможно, без знака) символ и выполнить арифметику для этого:

void print_function_instructions(void* fptr, size_t func_len) {
    unsigned char* func_ptr = reinterpret_cast<unsigned char*>(fptr);

    for (unsigned char i = 0; i < func_len; i++) 
        printf("%p (%2u): %x\n", func_ptr + i, i, func_ptr[i]); 
}

int change_page_permissions_of_address(void* address) {
    // Move the pointer to the page boundary
    unsigned char* addr = reinterpret_cast<unsigned char *>(address);

    int page_size = getpagesize();
    DWORD dwOldProtect;

    addr -= (uintptr_t)addr % page_size; 

    if (VirtualProtect(addr, page_size, PAGE_EXECUTE_READWRITE, &dwOldProtect) == -1) {
        return -1;
    }

    return 0;
}
0 голосов
/ 09 апреля 2019

Вы не можете делать арифметику с void указателями

#include <cstdio>

void print_function_instructions(void *func_ptr, size_t func_len) {
    for (unsigned char i = 0; i < func_len; i++) {
        unsigned char *instruction = (unsigned char*)func_ptr + i;
        printf("%p (%2u): %x\n", instruction, i, *instruction); 
    }
}

Вместо того, чтобы печатать func_ptr + i, вы должны напечатать instruction, это инициализировано с func_ptr + i, но приведение func_ptr кchar*.Void не имеет определенного размера (с ним нельзя сделать арифметику указателей), char имеет размер 1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...