2015-02-05 5 views
1

У меня есть драйвер, который я изменяю, который был написан кем-то еще в C. Поскольку мне нужно добавить некоторые вызовы функций C++, я теперь создаю драйвер с компилятором C++ по сравнению с компилятором C (в Visual Studio 2012). Когда я перешел на C++, я получил много ошибок сборки, все из которых я смог исправить, за исключением нескольких. Несколько ошибок связаны с вызовами одной и той же функции. Я много искал в Интернете, пытаясь найти решение этой проблемы без каких-либо успехов. Итак, ниже приведены компоненты этой проблемы, которые, я надеюсь, позволят кому-то помочь мне в этом вопросе.Указатель на указатель на функцию функции Void

Во-первых, здесь вызывается функция. Возможно, вам интересно, почему оригинальный разработчик S/W создал собственную функцию свободной памяти, когда они могли просто использовать функцию free() в стандартной библиотеке C. Я не знаю, почему это было, но так как он работал нормально, я не решаюсь изменить его.

void freeMemory(void **pBuffer) 
{ 
    BOOL result; 
    ASSERT(pBuffer != NULL); 

    // see if buffer is already been freed 
    if (*pBuffer == NULL) 
    { 
     return; 
    } 

    result = VirtualFree(
     *pBuffer,     // LPVOID lpAddress, // address of memory 
     0,       // SIZE_T dwSize,  // size of memory 
     MEM_RELEASE     // DWORD dwFreeType // operation type 
     ); 
    // see of we were able to successfully free the memory 
    if (result == FALSE) 
    { 
     ASSERT(FALSE); 
     return; 
    } 

    // Mark the buffer pointer as now being free 
    *pBuffer = NULL; 
} 

Так следующая часть этой головоломки является #define следующим образом:

#define FREE(pBuffer) freeMemory(&(pBuffer)) 

Наконец, ниже один из многих обращений к этой БЕСПЛАТНОЙ функции:

FREE(Buffer); 

В этот пример, «Буфер» является указателем на символ без знака.

unsigned char *Buffer; 

Для справочных целей, ошибка, что я получаю, для этого конкретного примера, «не может преобразовать параметр 1 из„неподписанные символ *“до„пустота **“»

Это было давно так как я много сделал с прямым C или C++, и указатели никогда не были моим сильным набором. Основываясь на этой ошибке, я предположил, что эта ошибка связана с тем, что она не обеспечивает приведение в вызов функции, но, учитывая, как функция free() используется из стандартной библиотеки C, похоже, что это не должно быть необходимым. Любая помощь в том, что мне нужно сделать в отношении того, как функция FREE вызывается для устранения этих ошибок, будет с большой благодарностью.

+0

Похожие: http://stackoverflow.com/questions/25427587/void- a-generic-pointer – Quentin

+0

Была ли память первоначально выполнена VirtualAlloc? – ryyker

+0

Это сообщение об ошибке должно читать «[...] от **' unsigned char ** '** до' void ** '[...]", и это преобразование не должно работать в C либо. – mafso

ответ

0

Проблемы, которую я имел при запуске вариаций коды, был с несовместимым использованием VirualFree и VirtualAlloc, то есть в вашем указанном примере кода я не мог видеть никаких признаков VirtualAlloc(), которое должно использоваться в сочетании с VirtualFree().

Кроме того, когда я пытался назначить память на определенный адрес с помощью VirtualAlloc(), он всегда терпел неудачу, поэтому я даю системе указать адрес. Ниже приведен фрагмент кода, демонстрирующий выделение и освобождение памяти страниц.

EDIT Теперь это обращается макрос вопрос, он использует предложение макроопределения от Jonaton (с двумя дополнительными ;).

Adapted from here: (это встроенный и побежал без ошибок, демонстрируя использование VirtualAlloc() используется в сочетании с VirtualFree())

#include <windows.h> 
#include <stdio.h> 
#include <stdlib.h>    

#define PAGES 100    

LPTSTR lpNxtPage;    
DWORD dwPages = 0;    
DWORD dwPageSize; 

void freeMemory(void **pBuffer); 

#define FREE(pBuffer) \ 
{ \ 
    void *tmp; \ 
    tmp = pBuffer; \ 
    freeMemory(&tmp); \ 
    pBuffer = tmp; \ 
} 

void main(void) 
{ 
    LPVOID lpvBase;    
    LPTSTR lpPtr;     
    BOOL bSuccess;     
    DWORD i;      
    SYSTEM_INFO sSysInfo;   

    GetSystemInfo(&sSysInfo);  


    dwPageSize = sSysInfo.dwPageSize; 


    lpvBase = VirtualAlloc(
        NULL,     
        PAGES*dwPageSize, 
        MEM_RESERVE,   
        PAGE_NOACCESS);  
    if (lpvBase == NULL)//do nothing 

    lpPtr = lpNxtPage = (LPTSTR) lpvBase; 


    // bSuccess = VirtualFree(
    //     lpvBase,  
    //     0,    
    //     MEM_RELEASE); 
    FREE(lpvBase) //replace in-line VirtualFree with macro 

    ; 
} 


void freeMemory(void **pBuffer) 
{ 
    BOOL result; 
    assert(pBuffer != NULL); 

    // see if buffer is already been freed 
    if (*pBuffer == NULL) 
    { 
     return; 
    } 

    result = VirtualFree(
     *pBuffer,     // LPVOID lpAddress, // address of memory 
     0,       // SIZE_T dwSize,  // size of memory 
     MEM_RELEASE     // DWORD dwFreeType // operation type 
     ); 
    // see of we were able to successfully free the memory 
    if (result == FALSE) 
    { 
     assert(FALSE); 
     return; 
    } 

    // Mark the buffer pointer as now being free 
    *pBuffer = NULL; 
} 
+0

ryyker - как указано в моих комментариях выше, если я заменил старый макрос новым, я теперь получаю «ошибка C2440: '=': не может преобразовать из 'void *' в 'unsigned char *'". Поскольку было всего несколько вызовов FREE(), я закончил устранение макроса и просто поместил код в строку, который устранил ошибки сборки. Пока я знаю, что он правильно освобождает память, я чувствую себя хорошо. По отношению к вам комментарий о использовании VirualAlloc() у программы есть еще одна функция, похожая на freeMemory, которая обертывает VirualAlloc() и эффективно соответствует вашему коду. – Pungo120

0

freeMemory Используется для создания безопасного, так как вы можете называть его дважды для одного и того же указателя без вреда. Мне это не нравится, это только скроет вашу ошибку, но очень часто встречается вокруг.

Причина этой ошибки объясняется here, как указано Квентином.

Альтернатива для вас кода:

#define FREE(pBuffer) \ 
{ \ 
    void *tmp; \ 
    tmp = pBuffer; \ 
    freeMemory(&tmp); \ 
    pBuffer = tmp; \ 
} 
+3

вам не хватает пары ';' в вашем ответе. – ryyker

+0

Я добавил необходимый ';' к строкам кода в ответе Джонатана, но теперь я получаю ошибку сборки для этого кода, в которой говорится: «Ошибка C2447:« {': отсутствует заголовок функции (формальный список старого стиля?) » – Pungo120

+0

@ Pungo120 - возможно ли это ссылка для использования прототипа функции? Кстати, я внедрил код Джонатана в ваш, запустил его, и 'VirtualFree (...)' не смог освободить память. Кроме этого, я не получаю сообщений об ошибках. Taht может быть потому, что второй аргумент равен 0. Я смотрю *** (документация) (https://msdn.microsoft.com/en-us/library/windows/desktop/aa366892%28v=vs.85% 29.aspx) ***. – ryyker

Смежные вопросы