I'm trying to display a simple message within my first MFC application.
Strangely, the first sample doesn't work, instead the second one works correctly.
auto text = std::to_wstring(1).c_str();
MessageBox(text, NULL, 0); // Not ok, the message is empty
auto temp = std::to_wstring(1);
MessageBox(temp.c_str(), NULL, 0); // Ok, display 1
Can you explain why of this behavior?
Yes, in the first example, the wstring created by the call to std::to_wstring only has the scope of the line. After the line executes, it is out of scope and its value is dubious.
In the second example, the wstring is still in scope and valid and so the call to .c_str() works.
No, the other answer is wrong. Look at the implementation of c_str(). c_str() returns basically a LPCWSTR... call it a const WCHAR* or const wchar_t* or whatever. However, the return of c_str() is to an internal pointer of wstring. The problem is that after the line of code executes, the wstring returned from to_wstring() is not valid and so the the pointer returned by c_str() is garbage. For fun, try the following code:
//cstr_.cpp
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char* argv)
{
auto temp = to_wstring(1).c_str();
wprintf(L"%s\n", temp);
auto temp2 = to_wstring(1);
wprintf(L"%s\n", temp2.c_str());
wstring ws = to_wstring(1);
auto temp3 = ws.c_str();
wprintf(L"%s\n", temp3);
}
I compiled the above from a VC++ shell prompt with: cl.exe cstr.cpp
If the other answer is correct, then the last line should have garbage or nothing output because according to the other answer, c_str() is a temp. But, if my answer is correct, then it should output 1 (which it does). If all else fails, look at the implementation source code.
Related
According to https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/makepath-s-wmakepath-s?view=vs-2019#generic-text-routine-mappings _makepath_s should return an error code on failure.
On my system this is not true, it gives an assert (Expression: (L"Buffer is too small" && 0)) and then terminates the program. In release it simply terminates the program.
The only way I found to keep my program running is to set an empty invalid parameter handler:
void myInvalidParameterHandler(const wchar_t* expression,
const wchar_t* function,
const wchar_t* file,
unsigned int line,
uintptr_t pReserved)
{
}
_set_invalid_parameter_handler(myInvalidParameterHandler);
But this is not recommended. The docs say that this handler should abort the program.
And I also think that this modifies all secure function which is not what exactly what I want.
So is there a better way to get _makepath_s behave like the docs say?
TIA Michael
VS2017, MFC
Edit
A small sample:
char Path[_MAX_PATH];
char drive[_MAX_DRIVE] = "C:";
char dir[_MAX_DIR] = "Thisisaverylongdirname01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
char fname[_MAX_FNAME] = "Thisisaverylongfilename012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
char ext[_MAX_EXT] = "txt";
_makepath(Path, drive, dir, fname, ext);
If I have a code for example like this:
#include <iostream>
using namespace std;
void swap(void** a) {
int tmp = 5;
void* b = &tmp;
a = &b;
}
int main()
{
int x=11;
void* y=&x;
void** z=&y;
swap(z);
void* a = *z;
cout << *(int*)a << endl;
return 0;
}
The code above prints 11, but I want to update the value of z (its address) to point to a place so I can print 5 (I mean update it). What should I do so that when I send z to the function and get back to main I can receive 5 instead of 11.
I'm just not that good with pointers.
EDIT: I must send to swap an argument with void**
You can't update the value of a void** (i.e. what it points to) by passing it to a function that takes a void**. That only allows to modify the pointed-to memory, not what address the pointer you pass to the function points to.
To update what it points to, the parameter should be a void**& or a void***.
Regardless of what solution you choose, the code you posted is extremely error prone and a hell to maintain. You should totally avoid it.
Also, note that &tmp becomes invalid as long as you exit the function, because the local variable tmp gets destroyed.
I have following code:
int _tmain(int argc, char** argv) {
bool g_graphics = true;
palPhysics * pp = 0;
#ifndef PAL_STATIC
PF -> LoadPALfromDLL();
#endif
char a[] = "Bullet";
std::string aa;
aa = std::string(argv[1]);
//PF->SelectEngine("Bullet");
DebugBreak();
PF -> SelectEngine(argv[1]);
//PF->SelectEngine(aa);
//debug
// assert(false);
pp = PF -> CreatePhysics();
}
I am trying to read in the command line argument no. 1 in this line:
PF->SelectEngine(argv[1]);
However, I only get the first letter of the argument. I have also tried changing
int _tmain(int argc, char** argv)
to
int _tmain(int argc, TCHAR** argv), but then I get
error:
error C2664: 'palFactory::SelectEngine' : cannot convert parameter 1 from 'TCHAR *' to 'const PAL_STRING &'
PAL_STRING is just a std::string.
This might be a simple one, but I am not sure how to convert TCHAR to std::string, especially since TCHAR is something else depending on compiler /environment settings. Is anyone aware of an easy way to get the command-line arguments to work, such that I don't need to convert anything myself, i..e maybe by changing the tmain function?
Thanks!
C
Update: example of invoking on command line:
Yep. so the way I invoke this on command line is:
progname.exe arg1 arg2,
where arg1 is a physics engine I am trying to load, and arg2 is a dae(physics file with physics info), so I go, specifically:
progname.exe Bullet E:/a.dae
Stepping into the line "PF->SelectEngine(argv[1]);" gives the following code:
bool palFactory::SelectEngine(const PAL_STRING& name) {
#ifdef INTERNAL_DEBUG
printf("palFactory::SelectEngine: this = %p\n", this);
#endif
SetActiveGroup(name); // also calls RebuildRegistry
return isClassRegistered("palPhysics");
}
, in this case, when debugging, I can see that const PAL_STRING& name, i.e. the string, is just "B", instead of what I would expect it to be, which is "Bullet", my command line argument I have passed in the command line.
I've been plauged by this problem for years. The only solution I've been able to find is to NOT USE Visual Studio. I've had to fall back to using other compilers when I must be able to process command-line args. Specifically, I've been using the Digital Mars compiler successfully. It handles the command-line args correctly. I use the VS environment for intellisense and debugging, then compile with DMC to deploy.
---edit below---
Turns out, I just wasn't asking the right question. I finally asked the right question, and got the right answer! See link below.
What is the difference between _tmain() and main() in C++?
does anyone know why this code is not working?
#include "stdafx.h"
#include <windows.h>
#include <WinCrypt.h>
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t *bin = TEXT("ProductID:1233===>55555");
BYTE out2[1000];
DWORD olen;
olen = 1000;
if (CryptStringToBinary(bin, 0, 1, out2, &olen, 0, 0) == 0)
{
wprintf(TEXT("Failure\n"));
}
else
{
//wprintf(TEXT("rn%s\n"),out2);
wprintf(TEXT("Success\n"));
}
system("pause");
return 0;
}
Thank you very much in advance!
Tom
Because you specified a length (parameter 2) of 0?
Edit: Just to clarify our eventual solution in the comments below, the code in the original question (since edited) contained two errors:
It was calling CryptBinaryToString instead of CryptStringToBinary. Since it's invalid to pass a 0 in the second parameter to CryptBinaryToString, the function was failing.
It was passing 1 in the third parameter (dwFlags), which is interpreted as CRYPT_STRING_BASE64. Since the string to encrypt wasn't in base 64 (it contained invalid characters such as ':'), the function was failing. In general, passing a raw value instead of using an existing definition (e.g., CRYPT_STRING_BASE64) is not a good idea.
How can one convert a shared_ptr that points to a const object to a shared_ptr that points to a non-const object.
I am trying to do the following :
boost::shared_ptr<const A> Ckk(new A(4));
boost::shared_ptr<A> kk=const_cast< boost::shared_ptr<A> > Ckk;
But it does not work.
'boost::const_pointer_cast' will do what you're asking for, but the obligatory second half of the answer is that you probably shouldn't use it. 99% of the time when it seems like you need to cast away the const property of a variable, it means that you have a design flaw. Const is sometimes more than just window dressing and casting it away may lead to unexpected bugs.
Without knowing more details of your situation one can't say for certain. But no discussion of const-cast is complete without mentioning this fact.
use boost::const_pointer_cast, documentation.
the proper way should be this
boost::shared_ptr<A> kk (boost::const_pointer_cast<A>(Ckk));
std::const_cast_pointer makes a second managed pointer. After the cast you have a writable pointer and the original const-pointer. The pointee remains the same. The reference count has been increased by 1.
Note that const_cast is a builtin keyword, but const_pointer_cast is a template function in namespace std.
The writable pointer can then be used to change the value from under the shared_ptr<const T>. IMHO the writable pointer should only persist temporarily on the stack; otherwise there must be a design flaw.
I once wrote a small test program to make this clear to myself which I adapted for this thread:
#include <memory>
#include <iostream>
#include <cassert>
using namespace std;
typedef shared_ptr<int> int_ptr;
typedef shared_ptr<const int> const_int_ptr;
int main(void)
{
const_int_ptr Ckk(new int(1));
assert(Ckk.use_count() == 1);
cout << "Ckk = " << *Ckk << endl;
int_ptr kk = const_pointer_cast<int>(Ckk); // obtain a 2nd reference
*kk = 2; // change value under the const pointer
assert(Ckk.use_count() == 2);
cout << "Ckk = " << *Ckk << endl; // prints 3
}
Under UNIX or Windows/Cygwin, compile with
g++ -std=c++0x -lm const_pointer_cast.cpp