C++(Visual Studio 2012): Copying a function's parameter char* to a dynamically allocated one - char

I have this structure defined and a class in my project. It is a class that holds id numbers generated by GetIdUsingThisString(char *), which is a function that loads a texture file into GPU and returns an id(OpenGL).
The problem is, when I try to read a specific file, the program crashes. When I run this program in VS with debugging it works fine, but running .exe crashes the program(or running without debugging from MSVS). By using just-n-time debugger I have found out that, for num of that specific file, Master[num].name actually contains "\x5" added(concatenation) at the end of the file path, and this is only generated for this one file. Nothing out of this method could do it, and I also use this type of slash / in paths, not \ .
struct WIndex{
char* name;
int id;
};
class Test_Class
{
public:
Test_Class(void);
int AddTex(char* path);
struct WIndex* Master;
TextureClass* tex;
//some other stuff...
};
Constructor:
Test_Class::Test_Class(void)
{
num=0;
Master=(WIndex*)malloc(1*sizeof(WIndex));
Master[0].name=(char*)malloc(strlen("Default")*sizeof(char));
strcpy(Master[0].name,"Default");
Master[0].id=GetIdUsingThisString(Master[0].name);
}
Adding a new texture:(The bug)
int Test_Class::AddTex(char* path)
{
num++;
Master=(WIndex*)realloc(Master,(num+1)*sizeof(WIndex));
Master[num].name=(char*)malloc(strlen(path)*sizeof(char));
strcpy(Master[num].name,path);<---HERE
Master[num].id=GetIdUsingThisString(path);
return Master[num].id;
}
At runtime, calling AddTex with this file would have path with the right value, while Master[num].name will show this modified value after strcpy(added "\x5").
Question:
Is there something wrong with copying(strcpy) to a dynamically allocated string? If i use char name[255] as a part of the WIndex structure, everything works fine.
More info:
This exact file is called "flat blanc.tga". If I put it in a folder where I intended it to be, fread in GetIdUsingThisString throws corrupted heap errors. If I put it in a different folder it is ok. If I change it's name to anything else, it's ok again. If I put a different file and give it that same name, it is ok too(!!!). I need the program to be bug free of this kind of things because I won't know which textures will be loaded(if I knew I could simply replace them).

Master[num].name=(char*)malloc(strlen(path)*sizeof(char));
Should be
Master[num].name=(char*)malloc( (strlen(path)+1) * sizeof(char));
There was not place for the terminating NULL character
From http://www.cplusplus.com/reference/cstring/strcpy/:
Copies the C string pointed by source into the array pointed by
destination, including the terminating null character (and
stopping at that point).
The same happens here:
Master[0].name=(char*)malloc(strlen("Default")*sizeof(char));
strcpy(Master[0].name,"Default");

Based on the definitions (below) - you should use strlen(string)+1 for malloc.
A C string is as long as the number of characters between the beginning of the string and the terminating null character (without including the terminating null character itself).
The strcpy() function shall copy the string pointed to by s2 (including the terminating null byte)
Also see discussions in How to allocate the array before calling strcpy?

Related

8.3 format filenames received when files opened from context menu in Windows

I have edited the windows registry so that selected files can be opened with the program I made (from an option in context menu). Specifically, under specific file types I have added 'shell' key and under it a 'command' key with string containing "C:\MyProgram.exe %1". The file opens correctly, however my program receives the file name in old 8.3 format, and I need full file name for display. How should I fix this?
Side quest: How to open multiple files as multiple arguments in one program call instead of opening separate instances, each with only one argument(%1)?
The easiest way to get to the full path name is to call GetLongPathName. In C++ you would use something like the following:
std::wstring LongPathFromShortPath(const wchar_t* lpszShortPath) {
// Prevent truncation to MAX_PATH characters
std::wstring shortPath = L"\\\\?\\";
shortPath += lpszShortPath;
// Calculate required buffer size
std::vector<wchar_t> buffer;
DWORD requiredSize = ::GetLongPathNameW(shortPath.c_str(), buffer.data(), 0x0);
if (requiredSize == 0x0) {
throw std::runtime_error("GetLongPathNameW() failed.");
}
// Retrieve long path name
buffer.resize(static_cast<size_type>(requiredSize));
DWORD size = ::GetLongPathNameW(shortPath.c_str(), buffer.data(),
static_cast<DWORD>(buffer.size()));
if (size == 0x0) {
throw std::runtime_error("GetLongPathNameW() failed.");
}
// Construct final path name (not including the zero terminator)
return std::wstring(buffer.data(), buffer.size()-1);
}
For first part of question do that IInspectable suggested.
But if you want to do something more fancy, simple registry modification will not do the trick. You need Windows Shell Extension and implement Context Menu handler. Once I have made one, here are some useful links: here, here and here. And there are already similar questions like this

Solving tcsncpy_s.inl assertion (line 24)

I've a fairly simple program which needs user input in the form of a text string. I've a CLR form with an edit box and I need to take that input and pass it into my class which just copies it to a member variable.
In the Form.h code, handling the TextChanged event is...
int textLength = m_userDest->TextLength;
if (textLength > 2 && textLength < 5)
{
// Could be an ICAO code in here
char dest[5];
String^ text = m_userDest->Text->ToUpper();
sprintf_s(dest, 5, "%s", text);
airTraffic.SetUserDest(dest);
}
My class (airTraffic) SetUserDest function is just
void CAirTraffic::SetUserDest(char* dest)
{
strncpy_s(m_userDest, 5, dest, 5);
}
When this is run I get this debug assertion, it doesn't stay on the screen and automatically clears after a few seconds.
Debug Assertion Failed!
Program: ...sual Studio 2010\Projects\FSAirTraffic\Debug\FSAirTraffic.exe
File: f:\dd\vctools\crt_bld\self_x86\crt\tcsncpy_s.inl
Line: 24
Expression: ((_Dst)) != NULL && ((_SizeInBytes)) > 0
I don't have an f:\ drive so I'm guessing this is some internal Microsoft(?) code so I can't see the context of the assertion and exactly what it's problem is. I don't have a file called tcsncpy_s.inl on my machine.
If I don't call my class function then there's no assertion so I assumed that was the problem.
Curiously though, when stepping through the debugger the assertion occurs as I step out of the TextChanged event, with the rest of the functions operating as intended (as far as I can see).
Does anyone know what the problem is and how I can go about solving it?
I don't understand how your code works. You use m_userDest twice, first it appears to be a pointer to a structure of some sort, maybe a handle to a TextBox control:
int textLength = m_userDest->TextLength;
Later you pass it to strncpy_s, which needs a char*, not a pointer to some structure.
void CAirTraffic::SetUserDest(char* dest)
{
strncpy_s(m_userDest, 5, dest, 5);
}
While it's possible for a structure to implicitly convert to a char*, it's not possible for a structure pointer to do so. Perhaps there's a smart pointer involved? Or you are using the same member variable name for completely different purposes in different classes1?
In any case, strncpy_s is inspecting the value of its first argument and not liking it.
1 Note that the new "wisdom" saying not to use Hungarian notation has destroyed the ability to understand this code in textual form. We don't have an IDE providing mouseover information about the data type of variables. Applications Hungarian is still a good idea in the real world, despite how many "best practices" documents decry it. Amazing how many code style documents are written from a purely theoretical basis.

passing pointers

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!

How to convert between shared_ptr<FILE> to FILE* in C++?

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.

UnicodeString storage type

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;
}

Resources