This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
I'm relatively new to C++ and the Windows API (coming from a Java background) and I was just playing around with the Windows API calling MessageBox and other simple functions until I tried to pass a concatenated string from a custom function to MessageBox where I noticed a weird output in the generated window.
This is the suspicious function:
const char* addFoo(const char* strInput)
{
return ("foo-" + std::string(strInput)).c_str();
}
It just returns the original input with a foo- added in front. (I hope I'm not doing anything incredibly wrong there)
In main I then do two calls to MessageBox first without calling the function but instead doing all the calculation on the fly, and afterwards calling the function:
const char* a = "bar";
MessageBox(NULL, ("foo-" + std::string(a)).c_str(), "The Foobar Experiment", MB_OK);
MessageBox(NULL, addFoo(a), "The Foobar Experiment", MB_OK);
This is the result I get by doing the string concatenation on the fly (case 1):
The result I get by calling the function addFoo (case 2):
Does anyone have any idea why I'm getting these unreadable characters on the generated window by using my addFoo function? Thanks in advance and sorry for the long post.
There are two fundamentally wrong things in your code, one being C++ related, the other being Windows related.
First, you are returning a pointer to a local entity, namely the return value of c_str() which is a pointer. Returning pointers to local variables is undefined behavior. What you want to do is return a string, not a pointer. In C++, there are string types such as std::string and std::wstring that implement the correct copy semantics that are required to have objects returned safely without error.
#include <string>
std::string addFoo(const char* strInput)
{
return "foo-" + std::string(strInput);
}
The second thing wrong with your code is that in the Windows world, you have basically two types of applications with respect to character type. You have the MBCS application, and Unicode application.
If you built a Unicode application, your calls to MessageBox would not have compiled successfully, since MessageBox takes wide character strings, not char based strings. In this case, the proper string type to use would be std::wstring.
You more than likely built an MBCS application, which in this day and age are becoming very rare.
const char* addFoo(const char* strInput)
{
return ("foo-" + std::string(strInput)).c_str();
}
This returns a pointer to a local temporary string, and its memory is released when your message box is shown.
Replace it by a std::string in your case:
std::string addFoo(const char* strInput)
{
return std::string("foo-") + strInput; // not sure about the syntax here
}
Then, std::string object manages its memory correctly and will make the string pointer remain alive for long enough for the message box to display it. You'll need to include <string> to get this defined.
Then, you can use:
std::string temp = addFoo( a );
MessageBox(NULL, temp.c_str(), "The Foobar Experiment", MB_OK);
Related
I'm trying to convert the address of a pointer to a wxString of the wxWidgets library.
I have this book that presents a console based example to explain the input/output stream system in C++. Here we can print the address of some pointers without much complications using
const char *const variable = "again";
cout << static_cast<void*>(variable);
So far I can understand the example but (Now the complication)I want to make some GUI off the examples to train myself and explore the wxWidgets classes along with the book. I've successfully made some conversions with the As() method of the wxAny class and even compiled it without warnings or errors. But in execution time I get an "Assert failure" when trying to convert the types.
If I let the program continue it prints in my wxTextCtrl things like:
ﻌњ̎X(
Any ideas??
(btw I use CodeBlocks with Mingw32 and wxWidgets 3.0 in a windows 7 system)
this is the code that gives me the assert failure:
void ConsoleFrame::OnbtnFrase2Click(wxCommandEvent& event)
{
string chaine2("Value of the pointer: ");
void* puntero = &chaine2;
wxAny anyThing= puntero;
consoleText->AppendText(anyThing.As<wxString>());
}
This is the method that gives me the assert failure error.
Thanks to #Grady for correcting the code before.
Seems that I cannot convert a void* to a wxString. I have a gist of what may the problem be but, I cannot find a solution to the original problem of printing the address of a pointer in a text control (NOT the console screen)
A common way to do what you want in C++ is using std::stringstream (you need to #include <sstream>). The body of your function would then look like this:
string chaine2("Value of the pointer: ");
void* puntero = &chaine2;
stringstream tmpss;
tmpss << chaine2 << puntero;
consoleText->AppendText(tmpss.str());
If you just want to get a wxString containing everything that was output to that stream, you just do something like:
wxString mystr = tmpss.str();
I don't know what your question has to do with wxWidgets, but this works for me:
const char * dog = "dog";
std::cout << &dog;
I am no C++ expert.. but to me that looks like "output address of variable dog"
and if you want that as a string you could use a C++ string stream or just happy old C sprintf
char * addrString = (char *)malloc(sizeof(void *) * 2 + 3); // *2 bytes for hex rep, +3 for "0x" and null
sprintf(addrString, "%p",dog);
There is a difference between the address of a pointer and the contents of the pointer, especially with C-style (nul terminated sequence of characters).
For example:
const char * const text = "Some Text\n";
The variable text is a pointer to a string literal. The contents of the pointer is the location where the string literal resides; often called an address.
The expression, &text, represents the location or the address of the pointer. So if the pointer is residing at address 0x4000, the expression &text would return 0x4000; not the content of the pointer.
There are examples on StackOverflow for printing the address of a variable and the contents or the C-Style string.
So, do you want a wxString containing the address of a pointer or the string literal that the pointer points to?
At last!!
The answer to my question was here:
http://docs.wxwidgets.org/trunk/classwx_text_ctrl.html
This is the documentation of the text control. I just had to REDIRECT the output stream to the text control with:
wxStreamToTextRedirector redirect(myTextControl);
And now I use the cout object normally,
cout<<puntero;
and the output will be presented in the text control instead of a console screen. I could not create the wxString containing the address but so far this can at least show it. I know that from here on I can create a string from the contents of the text control and the member functions of it. If any of you guys have a better answer, I will gladly accep it. It is funny how the chapter of the book where I am is in/out streams and the solution to my problem is not presented in the book.
I'm trying to add two LPCWSTR Variables as in
Shader = L"shader.fx"
Path = L"Source/Shaders/"
return Path + Shader
I've tried a thousand different ways, but my latest has been this
LPCWSTR ShaderFile = GetShader(L"shader.fx");
....
LPCWSTR GetShader(std::wstring _Shader)
{
std::wstring ShaderPath = static_cast<std::wstring>(SHADER_DIRECTORY) + _Shader;
LPCWSTR Return = ShaderPath.c_str();
return Return;
}
Now when I put a break point on the return, the value seems fine, return = Source/Shaders/shader.fx as expected. But when I F10 back into my object, the ShaderFile variable turns out to be something completely random, a bunch of what seems like arabic symbols.
Could anyone point me in the right direction of what to do? As I said, the function seems to work fine, just when i F10 through the breakpoint back into my project the variable equals something completely different
What's happening is that you're returning an address to data that's being invalidated by the return, so everything will seem fine before the function returns, but immediately after the result, it's all (at least potentially) garbage.
If at all possible, just return the std::wstring, and somewhere in the calling code call its c_str() member function when you really need it in the form of a raw buffer.
If you can't do that, and simply must return the result as a raw LPCWSTR, then you'll probably have to allocate the space dynamically:
LPCWSTR *ret = new char [ShaderPath.size()];
strcpy(ret, ShaderPath.c_str());
return ret;
Then, the calling code will need to delete [] the memory when it's no longer needed.
You really want to avoid the latter, and just return an std::wstring though. It's much simpler and cleaner, and will save the nearly inevitable problems with either deleting the buffer before you're finished using it, or else forgetting to delete it when you are done using it (still serious problems in C, but essentially unheard of in decently written C++).
The wstring.c_str() returns the internal pointer of the string.
In your case the local variable is destroyed when you exit the function and hence the pointer returned is deallocated and you get unexpected result.
Possible solution would be to copy the string using the method wcscpy()
The problem is that the c_str() method is returning a pointer into the local variable ShaderPath's memory. When the function exits, ShaderPath is destroyed, along with the data pointed to by your LPCWSTR.
Why don't you just store the variable as a wstring, and whenever you need the LPCWSTR you can call c_str()?
std::wstring GetShader(std::wstring _Shader)
{
return static_cast<std::wstring>(SHADER_DIRECTORY) + _Shader;
}
Assuming you had a function Foo(LPCWSTR path), you would use it like:
Foo(GetShader(L"shader.fx").c_str());
or
std::wstring ShaderFile = GetShader(L"shader.fx");
Foo(ShaderFile.c_str());
I need a function that is supplied a LPTSTR and an enumerated value, constructs a string based on the value and puts it in the LPTSTR.
I've written the following function which uses an array of names indexed by an enumerated value:
bool GetWinClassName(const int &WinType, LPTSTR *className, const int bufSize)
{
bool allOk = true;
LPTSTR tempName = new TCHAR[bufSize];
_stprintf_s(tempName, bufSize, TEXT("Win%sClass"), g_WinNames[WinType]);
std::cout << (char*)tempName << std::endl;
if (FAILED(StringCchCopy(*className, (bufSize+1)*sizeof(TCHAR), tempName)))
{
allOk = false;
}
delete[] tempName;
return allOk;
}
(Originally I just had the _stprintf_s line using className instead of tempName, this has been broken up to find where the error lies.)
The above code compiles in VC2010 Express but gives an unhandled exception: "Access violation writing" to (presumably) *className when it tries to execute the StringCchCopy line.
I can get this to work by doing
className = new TCHAR[bufSize];
before calling the function (with a matching delete[] after it) but do I really need to do that each time I want to call the function?
I understand where the problem lies but not why which is hampering my efforts to come up with a workable solution. The problem appears to me to be that I can't put something in the LPTSTR (via _stprintf_s or StringCchCopy) unless I allocate it some memory by using new TCHAR[bufSize]. I've tried assigning it an intial value of exactly the same size but with the same results which is leading me to think that the memory allocation actually has nothing to do with it. Is it then somehow casting my LPTSTR into a TCHAR[]? I don't see how that's possible but at this stage, I'd believe anything.
Can someone please explain what I'm doing wrong? (Or at least where my understanding is wrong.) And a probably related question is why is my std::cout only showing the first character of the string?
wstring winClassName( int const winType )
{
return wstring( L"Win" ) + g_WinNames[winType] + L"Class";
}
But I'm just completely baffled why you have that global array of names etc.: it's probably a design level error.
do I really need to do that each time I want to call the function?
An LPTSTR value is not a string object, it is simply a pointer-to-TCHAR. If you do not allocate a buffer, where do you think the characters will go? You must make sure that the className pointer argument points to a memory buffer that you can write to. Whether you allocate a new buffer each time is up to you.
As Alf implies, a better alternative is to avoid the direct use of pointers and dynamically allocated arrays altogether, and return a string object.
why is my std::cout only showing the first character of the string?
Use std::wcout instead if UNICODE is defined.
Ps: This is more of a conceptual question.
I know this makes things more complicated for no good reason, but here is what I'm wondering. If I'm not mistaken, a const char* "like this" in c++ is pointing to l and will be automatically zero terminated on compile time. I believe it is creating a temporary variable const char* to hold it, unless it is keeping track of the offset using a byte variable (I didn't check the disassembly). My question is, how would you if even possible, add characters to this string without having to call functions or instantiating strings?
Example (This is wrong, just so you can visualize what I meant):
"Like thi" + 's';
The closest thing I came up with was to store it to a const char* with enough spaces and change the other characters.
Example:
char str[9];
strcpy(str, "Like thi")
str[8] = 's';
Clarification:
Down vote: This question does not show any research effort; it is unclear or not useful
Ok, so the question has been highly down voted. There wasn't much reasoning on which of these my question was lacking on, so I'll try to improve all of those qualities.
My question was more so I could have a better understanding of what goes on when you simply create a string "like this" without storing the address of that string in a const char* I also wanted to know if it was possible to concatenate/change the content of that string without using functions like strcat() and without using the overloaded operator + from the class string. I'm aware this is not exactly useful for dealing with strings in C++, but I was curious whether or not there was a way besides the standard ways for doing so.
string example = "Like thi" + "s"; //I'm aware of the string class and its member functions
const char* example2 = "Like this"; //I'm also aware of C-type Strings (CString as well)
It is also possible that not having English as my native language made things even worst, I apologize for the confusion.
Instead of using a plain char string, you should use the string library provided by the C++ library:
#include <string>
#include <iostream>
using namespace std;
int main()
{
string str = "Like thi";
cout << str << endl;
str = str + "s";
cout << str << endl;
return 0;
}
Normally, it's not possible to simply concatenate plain char * strings in C or C++, because they are merely pointers to arrays of characters. There's almost no reason you should be using a bare character array in C++ if you intend on doing any string manipulations within your own code.
Even if you need access to the C representation (e.g. for an external library) you can use string::c_str().
First, there is nothing null terminated, but the zero terminated. All char* strings in C end with '\0'.
When you in code do something like this:
char *name="Daniel";
compiler will generate a string that has a contents:
Daniel\0
and will initialize name pointer to point at it at a certain time during program execution depending on the variable context (member, static, ...).
Appending ANYTHING to the name won't work as you expect, since memory pointed to by name isn't changeable, and you'll probably get either access violation error or will overwrite something else.
Having
const char* copyOfTheName = name;
won't create a copy of the string in question, it will only have copyOfTheName point to the original string, so having
copyOfTheName[6]='A';
will be exactly as
name[6]='A';
and will only cause problems to you.
Use std::strcat instead. And please, do some investigating how the basic string operations work in C.
I know there is a similarly titled question already on SO but I want to know my options for this specific case.
MSVC compiler gives a warning about strcpy:
1>c:\something\mycontrol.cpp(65): warning C4996: 'strcpy': This function or
variable may be unsafe. Consider using strcpy_s instead. To disable
deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
Here's my code:
void MyControl::SetFontFace(const char *faceName)
{
LOGFONT lf;
CFont *currentFont = GetFont();
currentFont->GetLogFont(&lf);
strcpy(lf.lfFaceName, faceName); <--- offending line
font_.DeleteObject();
// Create the font.
font_.CreateFontIndirect(&lf);
// Use the font to paint a control.
SetFont(&font_);
}
Note font_ is an instance variable. LOGFONT is a windows structure where lfFaceName is defined as TCHAR lfFaceName[LF_FACESIZE].
What I'm wondering is can I do something like the following (and if not why not):
void MyControl::SetFontFace(const std::string& faceName)
...
lf.lfFaceName = faceName.c_str();
...
Or if there is a different alternative altogether then let me know.
The reason you're getting the security warning is, your faceName argument could point to a string that is longer than LF_FACESIZE characters, and then strcpy would blindly overwrite whatever comes after lfFaceName in the LOGFONT structure. You do have a bug.
You should not blindly fix the bug by changing strcpy to strcpy_s, because:
The *_s functions are unportable Microsoft inventions almost all of which duplicate the functionality of other C library functions that are portable. They should never be used, even in a program not intended to be portable (as this appears to be).
Blind changes tend to not actually fix this class of bug. For instance, the "safe" variants of strcpy (strncpy, strlcpy, strcpy_s) simply truncate the string if it's too long, which in this case would make you try to load the wrong font. Worse, strncpy omits the NUL terminator when it does that, so you'd probably just move the crash inside CreateFontIndirect if you used that one. The correct fix is to check the length up front and fail the entire operation if it's too long. At which point strcpy becomes safe (because you know it's not too long), although I prefer memcpy because it makes it obvious to future readers of the code that I've thought about this.
TCHAR and char are not the same thing; copying either a C-style const char * string or a C++ std::string into an array of TCHAR without a proper encoding conversion may produce complete nonsense. (Using TCHAR is, in my experience, always a mistake, and the biggest problem with it is that code like this will appear to work correctly in an ASCII build, and will still compile in UNICODE mode, but will then fail catastrophically at runtime.)
You certainly can use std::string to help with this problem, but it won't get you out of needing to check the length and manually copy the string. I'd probably do it like this. Note that I am using LOGFONTW and CreateFontIndirectW and an explicit conversion from UTF-8 in the std::string. Note also that chunks of this were cargo-culted out of MSDN and none of it has been tested. Sorry.
void MyControl::SetFontFace(const std::string& faceName)
{
LOGFONTW lf;
this->font_.GetLogFontW(&lf);
int count = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
faceName.data(), faceName.length(),
lf.lfFaceName, LF_FACESIZE - 1)
if (count <= 0)
throw GetLastError(); // FIXME: use a real exception
lf.lfFaceName[count] = L'\0'; // MultiByteToWideChar does not NUL-terminate.
this->font_.DeleteObject();
if (!this->font_.CreateFontIndirectW(&lf))
throw GetLastError(); // FIXME: use a real exception
// ...
}
lf.lfFaceName = faceName.c_str();
No you shouldn't do that because you are making a local copy of the poitner to the data held inside the std::string. If the c++ string changes, or is deleted, the pointer is no longer valid, and if lFaceName decides to change the data this will almost certainly break the std::string.
Since you need to copy a c string, you need a 'c' function, then strcpy_s (or it's equivalent) is the safe alternative
Have you tried? Given the information in your post, the assignment should generate a compiler error because you're trying to assign a pointer to an array, which does not work in C(++).
#include <cstdio>
#include <string>
using namespace std;
struct LOGFONT {
char lfFaceName[3];
};
int main() {
struct LOGFONT f;
string foo="bar";
f.lfFaceName = foo.c_str();
return 0;
}
leads to
x.c:13: error: incompatible types in assignment of `const char*' to `char[3]'
I'd recommend using a secure strcpy alternative like the warning says, given that you know the size of the destination space anyway.
#include <algorithm>
#include <iostream>
#include <string>
enum { LF_FACESIZE = 256 }; // = 3 // test too-long input
struct LOGFONT
{
char lfFaceName[LF_FACESIZE];
};
int main()
{
LOGFONT f;
std::string foo("Sans-Serif");
std::copy_n(foo.c_str(), foo.size()+1 > LF_FACESIZE ? LF_FACESIZE : foo.size()+1,
f.lfFaceName);
std::cout << f.lfFaceName << std::endl;
return 0;
}
lf.lfFaceName = faceName.c_str(); won't work for two reasons (assuming you change faceName to a std:string)
The lifetime of the pointer returned by c_str() is temporary. It's only valid as long as the fileName object doesn't change and in alive.
The line won't compile. .c_str() returns a pointer to a char, and lfFaceName is a character array and can't be assigned to. You need to do something to fill in the string array, to fill in the bytes at lfFaceName, and pointer assignment doesn't do that.
There isn't anything C++ that can help here, since lfFaceName is a C "string". You need to use a C string function, like strcpy or strcpy_s. You can change your code to:
strcpy_s(lf.lfFaceName, LF_FACESIZE, faceName);