Atribuindo uma região a um ponteiro; [RESOLVIDO]

1. Atribuindo uma região a um ponteiro; [RESOLVIDO]

lucas
1lucas1

(usa Linux Mint)

Enviado em 21/02/2018 - 21:44h

suponhamos que eu tenha uma variavel no endereço 0x7ffca2e6d720 , sendo assim como eu faço para o ponteiro acessar essa área da memoria .... estou tentando colocar
 *Ponteiro=&0x7ffca2e6d720; 
mas está dando erro



  


2. MELHOR RESPOSTA

Fernando
phoemur

(usa Debian)

Enviado em 21/02/2018 - 23:52h

Uma coisa é descobrir o endereço da memória que está sendo usado no momento, outra coisa é usá-lo literalmente... Não faça isso...

Pois a cada vez que você executa o programa o sistema operacional vai designar randomicamente um pedaço da memória para alocá-lo, de forma que esse seu endereço 0x7ffca2e6d720 vai ser diferente a cada execução...
Isso é feito assim para dificultar ataques.
Se os endereços de memória fossem sempre fixos era só compilar um programinha para acessar o local da memória com a senha do root ;-)
Se bem que um SO moderno não vai permitir você acessar memória que não é relacionada ao processo, dando SEGFAULT

Veja:
https://stackoverflow.com/questions/15638105/accessing-specific-memory-locations-in-c

3. Re: Atribuindo uma região a um ponteiro; [RESOLVIDO]

Fernando
phoemur

(usa Debian)

Enviado em 21/02/2018 - 23:56h

Veja como o endereço muda a cada execução:

Programa teste.cpp
#include <iostream>

int main()
{
using namespace std;
int i = 12345;

cout << &i << endl; // imprime o endereço de memória onde está o int i

return 0;
}


Saída:

[phoemur@notebook_lenovo.darkstar ~/cpp/teste]$g++ -o teste teste.cpp
[phoemur@notebook_lenovo.darkstar ~/cpp/teste]$./teste
0x7fff4144560c
[phoemur@notebook_lenovo.darkstar ~/cpp/teste]$./teste
0x7ffe3da7f89c
[phoemur@notebook_lenovo.darkstar ~/cpp/teste]$./teste
0x7ffe2ffa400c
[phoemur@notebook_lenovo.darkstar ~/cpp/teste]$./teste
0x7fffcc2edbbc
[phoemur@notebook_lenovo.darkstar ~/cpp/teste]$./teste
0x7ffdf645441c
[phoemur@notebook_lenovo.darkstar ~/cpp/teste]$./teste
0x7ffe03a1b92c
[phoemur@notebook_lenovo.darkstar ~/cpp/teste]$./teste
0x7ffd0198be6c
[phoemur@notebook_lenovo.darkstar ~/cpp/teste]$./teste
0x7ffd270d4dac



4. Re: Atribuindo uma região a um ponteiro; [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 22/02/2018 - 01:24h

Em C:
void *pv=(void *)0x12345678;
char *pc=(char *)0xFEDCBA9876543210;


Na verdade, como em C um ponteiro para void pode ser automaticamente convertido em qualquer outro tipo de ponteiro, você pode optar por usar sempre void * para converter o endereço.
int *pi=(void *)0x1111111111111111;
double *pd=(char *)0xCCCCCCCCCCCCCCCC;



Em C++, há mais de uma maneira, e isso implica algumas explicações.

Em princípio, possivelmente o jeito do C indicando o tipo duas vezes (porque em C++ não existe conversão automática partindo de void * para ponteiros de outros tipos) funcionaria, mas conversões de tipo ao estilo de C são consideradas mau estilo (e em alguns casos podem inferir uma conversão errada). A conversão de valor inteiro para ponteiro precisa ser feita, portanto, com uma conversão reinterpret_cast.
// Sendo explícito quanto ao tipo na declaração e na atribuição:
int *pi=reinterpret_cast<int *>(0x01234567);

// Sendo explícito quanto ao tipo na declaração e forçando o mesmo tipo na atribuição, mas sem repetir explicitamente:
char *pc=reinterpret_cast<decltype(pc)>(0x01234567);

// Fazendo o compilador inferir o tipo a partir do tipo do(s) dado(s) apontado(s).
auto *dyn_int_array=reinterpret_cast<int *>(0xFEDCBA9876543210); // Note que não há como distinguir entre um ponteiro para
// um único elemento e um que aponte para um array dinâmico.


Ao trabalhar com OO e tipos criados pelo usuário, algumas vezes pode ser interessante chamar os construtores dos objetos dentro da região alocada. Para tanto, a notação de placement new, que é uma versão sobrecarregada do operador new para criar objetos em regiões de memória previamente alocadas de alguma outra maneira, informadas através de um ponteiro para void.
#include <new>  // Necessário para ter acesso a versões sobrecarregadas padronizadas do operador new.

// Sendo explícito duas vezes quanto ao tipo.
float *pf=new(reinterpret_cast<void *>(0xBEEF15F00D) float; // Para tipo nativo, sem chamar construtor default.

// Usando dedução de tipo a partir do tipo do dado apontado.
auto *pu=new(reinterpret_cast<void *>(0x1EA7F00D) unsigned(); // Para tipo nativo, chamando "construtor" default (atribui valor zero ao elemento).
auto *pn=new(reinterpret_cast<void *>(0x1A7EBEEF) double(3.14159265); // Para tipo nativo, chamado "construtor" de cópia.

struct tipo_X {
tipo_X(){ /* ... */ }
virtual ~tipo_X(){ /* ... */ }
};

class tipo_Y: public tipo_X {
tipo_Y() { /* ... */ }
tipo_Y(int i, char c){ /* ... */ }
~tipo_Y(){ /* ... */ }
};

// Sendo explícito duas vezes quanto ao tipo:
tipo_X *pX=new(reinterpret_cast<void *>(0xDEADBEEF)) tipo_X; // Chama o construtor default do dado do tipo tipo_X usando a região de
// memória indicada para conter o objeto.

// Fazendo o compilador inferir o tipo a partir do tipo do(s) dado(s) apontado(s).
auto *dyn_Y_array=new(reinterpret_cast<void *>(0xA11FED0FBEEF)) tipo_Y[500]; // Array com 500 elementos do tipo tipo_Y, chamando construtor
// default para cada elemento.

// Posso usar polimorfismo, também (ponteiro para classe base aponta para objeto de classe derivada).
tipo_X *pXd=new(reinterpret_cast<void *>(0xDEAFEE1) tipo_Y(1, 'a'); // Chama construtor arbitrário.


Em tempo: não cabe chamar delete (ou delete []) em áreas alocadas com placement new (ao menos não com a versão padrão), pois ela só faz a criação dos objetos, não uma alocação de fato. Se você precisar destruir os objetos por elas alocados, esse será uma daqueles raros casos em que cabe chamar o destrutor explicitamente (e.g. “pXd->~tipo_X();”, que, por ser virtual, e por estar ligado a um objeto derivado no exemplo acima, var chamar realmente o destrutor de tipo_Y).


5. Re: Atribuindo uma região a um ponteiro; [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 22/02/2018 - 01:35h

phoemur escreveu:

Uma coisa é descobrir o endereço da memória que está sendo usado no momento, outra coisa é usá-lo literalmente... Não faça isso...


Dependendo do caso, ele pode querer exatamente isso. Se a “variável” em questão for, por exemplo, uma região de I/O mapeada em memória, ou um vetor de interrupções, ou se ele estiver num hardware embarcado que não um PC, ou outros casos.

Pois a cada vez que você executa o programa o sistema operacional vai designar randomicamente um pedaço da memória para alocá-lo, de forma que esse seu endereço 0x7ffca2e6d720 vai ser diferente a cada execução...


Isso pode ser verdade ou pode não ser. Em versões modernas do Linux, normalmente é. No Windows, até o XP, pelo menos, nem sempre era.

Isso é feito assim para dificultar ataques.
Se os endereços de memória fossem sempre fixos era só compilar um programinha para acessar o local da memória com a senha do root ;-)


Se e somente se o kernel entregasse essa memória para o processo. Isso não tem nada a ver com o endereço ser fixo ou não.

Se bem que um SO moderno não vai permitir você acessar memória que não é relacionada ao processo, dando SEGFAULT


Aí, sim!






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts