2015-01-23 3 views
-5

У меня есть этот код:Трассировка адреса указателей в отладчике

void WriteToConsole(IMAGE_NT_HEADERS *ntHeader) 
    { 
    std::cout << "AddressOfEntryPoint = " << 
     ntHeader->OptionalHeader.AddressOfEntryPoint << std::endl; 
    } 
    void main() 
    { 
    //something 
    IMAGE_NT_HEADERS *NtHeader = GetWinNTHeader(dosHeader->e_lfanew); 
    WriteToConsole(NtHeader); 
    } 

Почему адреса NtHeader и ntHeader отличаются? Я отслеживаю адреса с помощью отладчика.

IMAGE_NT_HEADERS * GetWinNTHeader(long offset) 
{ 
    // IMAGE_NT_HEADERS size is 120 
    char buffer[120]; 
    file.seekg(offset); 
    file.read(buffer, 120); 
    IMAGE_NT_HEADERS* pHeader = (IMAGE_NT_HEADERS*)(buffer); 
    if (IsBadReadPtr(pHeader, sizeof(IMAGE_NT_HEADERS))) 
     return NULL; 
    if (pHeader->Signature != IMAGE_NT_SIGNATURE) 
     return NULL; 
    return pHeader; 
} 
+6

вы создаете указатель, инициализируя его, а затем печатаете его впервые в этой функции ... так, откуда вы знаете, что он изменился? – basav

+0

main() должен возвращать int. Оптимизирующий компилятор, вероятно, забудет значение NTHeader, потому что он не нужен после вызова. Попытайтесь распечатать его до и после вызова, и он будет таким же. – gnasher729

+1

Ваш код в порядке, но 'OptionalHeader.AddressOfEntryPoint' не такой же, как' NtHeader'. –

ответ

2

Я полагаю, вы используете какой-то отладчик, чтобы увидеть значение NtHeader.
Значение «изменяется», так как оно выделено в стеке и после того, как вы вызвали WriteToConsole, вы покидаете область действия, что приводит к освобождению NtHeader.

EDIT:

Тот факт, что NtHeader выделяется в основной() делает этот вопрос несколько бессмысленно, потому что, почему бы вы заботитесь о значении переменных, если программа собирается выйти?

+0

И что мне нужно делать? – EXTRAM

+0

изменить его область действия, если вы хотите использовать его после этого – Axalo

+0

Могу ли я сделать это, чем я не делаю NTHeader глобальным? – EXTRAM

0

это то, что вы ищете я думаю:

#include <iostream> 
#include <string> 

using namespace std; 

void WriteToConsole(char *&ntHeader) 
    { 
    std::cout << "AddressOfEntryPoint = " << 
     &ntHeader << std::endl; 
    } 


int main() 
{ 

    //something 
    char *NtHeader = "hello"; 
std::cout << "AddressOfEntryPoint = " << 
     &NtHeader << std::endl; 
    WriteToConsole(NtHeader); 

return 0; 
} 

выход: AddressOfEntryPoint = 0x7fff7a90b168 AddressOfEntryPoint = 0x7fff7a90b168

Теперь, если вы измените его, чтобы пройти через указатель,

void WriteToConsole(char *ntHeader) 

adn называют это таким образом, WriteToConsole(NtHeader);,

Затем вы получаете разные адреса. AddressOfEntryPoint = 0x7fffae028ca8 AddressOfEntryPoint = 0x7fffae028c88

Если вы DONOT хотите создать копию и хотят того же adddress вы всегда пройти по ссылке.

0

Основная проблема, независимо от того, что ваша функция пытается сделать, заключается в том, что вы возвращаете адрес локальной переменной. Это неопределенное поведение.

В принципе, вы делаете это:

IMAGE_NT_HEADERS * GetWinNTHeader(long offset) 
{ 
    // IMAGE_NT_HEADERS size is 120 
    char buffer[120]; 
    //... 
    IMAGE_NT_HEADERS* pHeader = (IMAGE_NT_HEADERS*)(buffer); 
    //... 
    return pHeader; 
} 

Поскольку pHeader является псевдонимом для buffer, вы возвращаете адрес локальной переменной, buffer.

Решение в основном - don't do this. Никогда не возвращайте ссылку или указатель на локальную переменную.

Вот одно решение, используя-структуру:

struct HeaderBuffer 
{ 
    char buffer[120]; 
}; 

HeaderBuffer GetWinNTHeader(long offset) 
{ 
    // IMAGE_NT_HEADERS size is 120 
    HeaderBuffer hBuffer; 
    file.seekg(offset); 
    file.read(hBuffer.buffer, 120); 
    IMAGE_NT_HEADERS* pHeader = (IMAGE_NT_HEADERS*)(hBuffer.buffer); 
    if (IsBadReadPtr(pHeader, sizeof(IMAGE_NT_HEADERS))) 
     hBuffer.buffer[0] = 0; 
    else 
    if (pHeader->Signature != IMAGE_NT_SIGNATURE) 
     hBuffer.buffer[0] = 0; 
    return hBuffer; 
} 

void WriteToConsole(IMAGE_NT_HEADERS *ntHeader) 
{ 
    std::cout << "AddressOfEntryPoint = " << 
     ntHeader->OptionalHeader.AddressOfEntryPoint << std::endl; 
} 

Вызывающий будет выглядеть примерно так:

int main() 
{ 
    HeaderBuffer buf = GetWinNTHeader(dosHeader->e_lfanew); 
    IMAGE_NT_HEADERS *NtHeader = static_cast<IMAGE_NT_HEADERS*>(buf.buffer); 
    WriteToConsole(NtHeader); 
} 

Примечание: Это не был составлен, так что надо знать об этом.

В принципе, функция возвращает буфер символов, заключенный в структуру.Вместо того, чтобы возвращать NULL, мы возвращаем буфер, который не имеет информации (буфер символов имеет strlen из 0).