I have this declared above:
char PandaImage[] = "images/panda.png";
SDL_Texture* PandaTexture = nullptr;
I have a function to create textures:
void LoadMedia( SDL_Texture *ThisTexture, char *Image )
{
SDL_Surface* TempSurface = nullptr;
.......................
ThisTexture = SDL_CreateTextureFromSurface( gRenderer, TempSurface );
I call it as:
LoadMedia( PandaTexture, PandaImage );
It builds, logs the image loaded and texture created, but no image
If I hard change the line ( use Panda directly instead of This ):
PandaTexture = SDL_CreateTextureFromSurface( gRenderer, TempSurface );
My image is there.
I have always had trouble with & * and passing.
Is there a good, simple help for me?
Thanks for your kind help - back to Google for now
In short, I think you could solve your problem by changing the function to:
void LoadMedia( SDL_Texture** thisTexture, char* Image)
{
...
(*thisTexture) = SDL_CreateTextureFromSurface( gRenderer, TempSurface);
}
And by calling the function using:
LoadMedia( &PandaTexture, PandaImage);
An explanation:
Variables and Pointers
A variable is used to store data (a primitive or a class instance). For example:
int a = 10;
stores an integer in memory. This means, that symbol 'a' now represents number 10, which is stored somewhere in your computer's memory as 4 bytes.
A pointer is used to store an address (this address points towards a variable). For example:
int* a_address = 1234;
says that there is an integer stored at address 1234 in your computer's memory. A pointer always takes up the same amount of space (4 bytes on a 32 bit machine and 8 bytes on a 64 bit machine), as it simply stores an address.
Getting the Address of a Variable [&]
You will rarely ever set the address of a pointer yourself. Often, pointers are the result of a "new" call. Using "new" reserves memory to store an instance of the class you want to create, and returns the address of the object. In essence, it says: "I created an object for you, and you can find it at this location in your memory".
Alternatively, when you have a normal variable (primitive of class instance), you can find its address by using the & character. For example:
int a = 10;
int* a_address = &a;
says: "store the location of variable a in pointer a_address. Why would you do this? Say you have a very large instance (for example an SDL_Texture consisting of many, many pixels) and you want to pass it to a function (or pass it back outside of the function). If you were to pass it to the function as SDL_Texture thisTexture, you are copying the entire object (a so-called pass by value). This is time consuming. Alternatively, you could simply pass the address to the function, as an SDL_Texture * thisTexture. This is a so called pass by reference, and it is much faster as you can imagine.
Getting the Variable at an Address [*]
Obviously, if you have an address, you also need a way to get the actual variable at that address. This is done using the * character. It is called "dereferencing". For example:
int a = 10;
int* a_address = &a;
int b = (*a_address);
This last line says: "Give me the variable, stored at address a_address, and put it in b".
Function Parameters Going Out-of-scope
When a function ends, its local variables (including parameters) go out-of-scope. This means that their memory is freed (for variables, not for dynamically allocated objects stored as pointers!). Their values will be forgotten. In your case, you are passing an SDL_Texture * as a parameter. This means, a copy is made of the address stored in PandaTexture. This address is copied over to thisTexture. You then write the return value of SDL_CreateTextureFromSurface to thisTexture. Next the function ends, and thisTexture goes out-of-scope. As a result, the location of your SDL_Texture (the SDL_Texture * pointer) is lost forever. You actually want to store the address to pointer PandaTexture, but as you can see, the address is only written to thisTexture.
Solution: How to Fix your Function
We can fix this by passing a pointer, to your pointer called PandaTexture. A "pointer to a pointer" is written as:
SDL_Surface** thisTexture;
We want to pass the address of pointer PandaTexture to this. This way, we can write to PandaTexture from inside your method! After all, we know where PandaTexture stores its pointer in memory, allowing us to change it. To actually put the address of PandaTexture in it, we need to use the & character in the function call as such:
LoadMedia(&PandaTexture, PandaImage);
Next, inside of our function, we want to change the value of PandaTexture. However, we were passed &PandaTexture and not PandaTexture itself. To write the value of &PandaTexture (the address where our texture will be stored), we need dereferencing, as such:
(*thisTexture) = SDL_CreateTextureFromSurface(gRenderer, TempSurface);
This works because: "thisTexture is a pointer to a pointer to an SDL_Texture (aka an SDL_Texture**). By dereferencing it, we obtain a pointer to an SDL_Texture (aka an SDL_Texture*). Here we can store the return value of the SDL_CreateTextureFromSurface function.
Why do we not run into out-of-scope issues here? Parameter thisTexture will still go out of scope, and its value will be forgotten. But! We didn't write to thisTexture, instead we wrote our SDL_Texture * pointer to the address that thisTexture points to! This bit of memory is not cleared due to scoping, so we can view the results from outside the function!
In summary, you can solve your problem using a pointer to a pointer. I hope the above clears up the concepts of pointers, variables, addresses and dereferencing a bit!
Related
I have some existing functions written in C that take pointers to two arrays and do some calculations on the data. I wanted to call those functions from PL/SQL as external procedures. Our data is stored in Oracle as a BLOB. So, I made a wrapper shared object to be called from PL/SQL. It felt like overkill to pass the BLOB into every wrapper function and parse it into these two arrays with every single external procedure call. So, instead I made a function called ParseBlobToArrays
which looks like:
int OracleBlobToDataArrays(OCIExtProcContext* ctx,OCILobLocator* blob,
//some other stuff I can't post used to parse blob,
unsigned int* address1, unsigned int* address2)
{
//this isn't all the code, error checking etc here as well
unsigned char* buf = OCIExtProcAllocCallMemory(ctx,lobLen ))
//read blob into allocated buf
double* arr1 = ParseToArray1(buf,//some additional params);
float** arr2 = ParseToArray2(buf,//some additional params);
*address1= (unsigned int)((uintptr_t) arr1);
*address2= (unsigned int)((uintptr_t) arr2);
}
I then return the addresses and feed them into each subsequent function that needs them and set them appropriately:
double OtherFunctionWrapper(unsigned int address1,unsigned int address2)
{
double* arr1 = (double*)address1;
float** arr2 = (float**)address2;
return DoCalculation(arr1,arr2);;
}
I then call a Free wrapper function I wrote which takes the addresses, casts again to appropriate types and then frees all the pointers.
There is a code smell I don't like:
The C code is passing memory addresses like this when PL/SQL doesn't seem to support a uintptr_t/64 bit binary integer (or even exposing these raw addresses at all). Casting and returning the address as a UINT32 and then moving this to 64 bit OS in the future would potentially blow up I believe, if the address doesn't fit in a UINT32.
I could parse the data into arrays and return them to PL/SQL as OCIColls, but then I need to use OCI specific data types etc. This is safer (I think?), but I already have the BLOB parsed and in memory to be used. Seems silly to pass data back to PL/SQL as PL/SQL supported types just to be passed in to other functions, when all I really need is a pointer to data that already exists in the format I want in memory.
Any advice on handling this differently? If the right option is to do everything with supported PL/SQL datatypes and return them accordingly, I will. But I am looking for other options as well to minimize duplicate code with each call to various calculation functions since speed of these external procedures is very important.
Thanks!
I am trying to write my own Allocator which can be used in STL. That far I could almost successfully finish but with one function I have my problem:
The Allocator used in STL should provide the function construct [example from a standard allocator using new & delete]:
// initialize elements of allocated storage p with value value
void construct (T* p, const T& value)
{
::new((void*)p)T(value);
}
I am stuck how to rewrite this using my own function which replaces the new keyword initializing it with the value.
This function construct is for example used in this code: fileLines.push_back( fileLine );
where
MyVector<MyString> fileLines;
MyString fileLine;
These are my typedefs where I use my own Allocator:
template <typename T> using MyVector = std::vector<T, Allocator<T>>;
using MyString = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
I am confused because here is allocated a pointer to T which can be for example [when I understood it correctly] MySstring.
Do I understand it correctly that the pointer - allocated by new - will have 10 bytes, when value is 123456789 and then the provided value is copied to the new pointer?
My question:
How to rewrite the one line of code using my own function? For me the difficult point is how to get the length of value [which can have any type] in order I can correctly determinate the length of the allocated block and how to copy it in order it works for all possible types T?
The new operator in the construct function does not allocate anything at all, it's a placement new call, which takes an already allocated chunk of memory (which needs to have been previously allocated some way, and at least as large as sizeof(T)) and initializes it as a T object by calling the constructor of T, pretending that the memory pointed to by p is a T object.
::new int(7) calls the default new operator, gets some memory big enough for an int, and constructs an int with the value 7 in it.
::new(ptr) int(7) takes a void* called ptr, and constructs an int with the value 7 in it. This is called "placement new".
The important part is what is missing from the second paragraph. It does not create space, but rather constructs an object in some existing space.
It is like saying ptr->T::T() ptr->int::int(7) where we "call the constructorofinton the memory location ofptr, exceptptr->T::T()orptr->int::int(7)are not valid syntaxes. Placementnew` is the way to explicitly call a constructor in C++.
Similarly, ptr->~T() or ptr->~int() will call the destructor on the object located at ptr (however, there is no ~int so that is an error, unless int is a template or dependent type, in which case it is a pseudo-destructor and the call it ignored instead of generating an error).
It is very rare that you want to change construct from the default implementation in an allocator. You might do this if your allocator wants to track creation of objects and attach the information about their arguments, without intrusively modifying the constructor. But this is a corner case.
I am trying to use a FILE pointer multiple times through out my application
for this I though I create a function and pass the pointer through that. Basically I have this bit of code
FILE* fp;
_wfopen_s (&fp, L"ftest.txt", L"r");
_setmode (_fileno(fp), _O_U8TEXT);
wifstream file(fp);
which is repeated and now instead I want to have something like this:
wifstream file(SetFilePointer(L"ftest.txt",L"r"));
....
wofstream output(SetFilePointer(L"flist.txt",L"w"));
and for the function :
FILE* SetFilePointer(const wchar_t* filePath, const wchar_t * openMode)
{
shared_ptr<FILE> fp = make_shared<FILE>();
_wfopen_s (fp.get(), L"ftest.txt", L"r");
_setmode (_fileno(fp.get()), _O_U8TEXT);
return fp.get();
}
this doesn't simply work. I tried using &*fp instead of fp.get() but still no luck.
You aren't supposed to create FILE instances with new and destroy them with delete, like make_shared does. Instead, FILEs are created with fopen (or in this case, _wfopen_s) and destroyed with fclose. These functions do the allocating and deallocating internally using some unspecified means.
Note that _wfopen_s does not take a pointer but a pointer to pointer - it changes the pointer you gave it to point to the new FILE object it allocates. You cannot get the address of the pointer contained in shared_ptr to form a pointer-to-pointer to it, and this is a very good thing - it would horribly break the ownership semantics of shared_ptr and lead to memory leaks or worse.
However, you can use shared_ptr to manage arbitrary "handle"-like types, as it can take a custom deleter object or function:
FILE* tmp;
shared_ptr<FILE> fp;
if(_wfopen_s(&tmp, L"ftest.txt", L"r") == 0) {
// Note that we use the shared_ptr constructor, not make_shared
fp = shared_ptr<FILE>(tmp, std::fclose);
} else {
// Remember to handle errors somehow!
}
Please do take a look at the link #KerrekSB gave, it covers this same idea with more detail.
I wonder how to make a variable within IDA Pro bound to some function so the next time I double click the variable it will send me to the function.
v1 = this
*v2 = Known-Function
At Some Different location:
char __stdcall ClassA__KnownFunction(ClassA *ClassA, void a2) {
commands.....
}
I know you can set type to int, struct, dword etc. But I am looking for some method to point the variable to already known offset/function in IDA Pro.
Function pointer is merely a variable that holds the address of a function; you cannot treat a variable like a constant. You have two options:
Add the name of the function as a comment (just for the sake of documentation).
Get rid of the variable assignment, hard-code the function address by editing the hex, and then perform the analysis again.
My application needs to manage a few of unicode strings (<10). The content of these strings is dynamic and can change through application run. To store strings I am using objects of type UnicodeString.
One approach to solving this problem is to create as many member variables as there are unicode strings like for example:
UnicodeString str1;
UnicodeString str2;
...
UnicodeString strN;
This solutions is pretty simple at least at first glance. But there is problem with scalability. If the number of string would rise in the future, we risk creating hard-to-read bigg code. So I thougth creating something like this for managing strings:
std::map<HWND, UnicodeString> file_names; ///< member variable of form TForm1
Every string is connected with some edit box. I can use window handle as key to dictionary.
What I don't understand - who should be responsible for allocating and deallocating space for storing unicode string in this case? Lets say I create UnicodeString variable on local stack:
void TForm1::ProcessFile(TEdit *edit_box)
{
UnicodeString str = "C:\\Temp\\ws.gdb";
file_name[edit_box->Handle] = str;
}
Will the content of str variable survive end of member function ProcessFile?
The memory storage of a UnicodeString is reference counted and managed by the RTL for you. You do not need to worry about deallocating it yourself, unless you allocate the UnicodeString itself using the new operator. In your code snippet, the str variable will be freed when ProcessFile() exits, but its contents will survive because file_name still has an active reference to it.
Do not use an HWND as the key for your std::map. The window managed by the TWinControl::Handle property is dynamic and can change value during the lifetime of the app. You can, however, use the TEdit* pointer instead:
std::map<TEdit*, UnicodeString> file_names;
void TForm1::ProcessFile(TEdit *edit_box)
{
UnicodeString str = "C:\\Temp\\ws.gdb";
file_names[edit_box] = str;
}