Use a char array in a std::string in C++11 - c++11

I'm not sure if this is safe, what will happen when the string gets out of scope?:
std::string tmp_str( strdup("wlan0"));
I know that strdup uses malloc to allocate new space for the string which will be used by tmp_string.
I'm not interested in a solution, I would like to know if there will be any issue using strdup.

The std::string class copies the string, not the pointer to the string. That means that the memory allocated by strdup will be lost forever for your process.
There's simply no need to use strdup in that way. And besides that, string literals will exist for the life-time of the program, so pointers to them will never become invalid.

Related

SIGSEGV when writing to, but not reading from a memory location in golang

I was under the impression that using the unsafe package allows you to read/write arbitrary data. I'm trying to change the value the interface{} points to without changing the pointer itself.
Assuming that interface{} is implemented as
type _interface struct {
type_info *typ
value unsafe.Pointer
}
setting fails with a SIGSEGV, although reading is successful.
func data(i interface{}) unsafe.Pointer {
return unsafe.Pointer((*((*[2]uintptr)(unsafe.Pointer(&i))))[1])
}
func main() {
var i interface{}
i = 2
fmt.Printf("%v, %v\n", (*int)(data(i)), *(*int)(data(i)))
*((*int)(data(i))) = 3
}
Am I doing something wrong, or is this not possible in golang?
Hm... Here's how I understand your second code example currently, in case I've made an error (if you notice anything amiss in what I'm describing, my answer is probably irredeemably wrong and you should ignore the rest of what I have to say).
Allocate memory for interface i in main.
Set the value of i to an integer type with the value 2.
Allocate memory for interface i in data.
Copy the value of main's i to data's i; that is, set the value of the new interface to an integer type with the value 2.
Cast the address of the new variable into a pointer to length-2 array of uintptr (with unsafe.Pointer serving as the intermediary that forces the compiler to accept this cast).
Cast the second element of the array (whose value is the address of the value-part of i in data) back into an unsafe.Pointer and return it.
I've made an attempt at doing the same thing in more steps, but unfortunately I encountered all the same problems: the program recognizes that I have a non-nil pointer and it's able to dereference the pointer for reading, but using the same pointer for writing produces a runtime error.
It's step 6 that go vet complains about, and I think it's because, according to the package docs,
A uintptr is an integer, not a reference. Converting a Pointer to a uintptr creates an integer value with no pointer
semantics. Even if a uintptr holds the address of some object, the garbage collector will not update that uintptr's value if the object moves, nor will that uintptr keep the object from being reclaimed.
More to the point, from what I can tell (though I'll admit I'm having trouble digging up explicit confirmation without scanning the compiler and runtime source), the runtime doesn't appear to track the value-part of an interface{} type as a discrete pointer with its own reference count; you can, of course, trample over both the interface{}'s words by writing another interface value into the whole thing, but that doesn't appear to be what you wanted to do at all (write to the memory address of a pointer that is inside an interface type, all without moving the pointer).
What's interesting is that we seem to be able to approximate this behavior by just defining our own structured type that isn't given special treatment by the compiler (interfaces are clearly somewhat special, with type-assertion syntax and all). That is, we can use unsafe.Pointer to maintain a reference that points to a particular point in memory, and no matter what we cast it to, the memory address never moves even if the value changes (and the value can be reinterpreted by casting it to something else). The part that surprises me a bit is that, at least in my own example, and at least within the Playground environment, the value that is pointed to does not appear to have a fixed size; we can establish an address to write to once, and repeated writes to that address succeed even with huge (or tiny) amounts of data.
Of course, with at least this implementation, we lose a bunch of the other nice-to-have things we associate with interface types, especially non-empty interface types (i.e. with methods). So, there's no way to use this to (for example) make a super-sneaky "generic" type. It seems that an interface is its own value, and part of that value's definition is an address in memory, but it's not entirely the same thing as a pointer.

is there a way to set the length of a std::string without modifying the buffer content?

According to the statements made in the answers of these questions
Is writing to &str[0] buffer (of a std:string) well-defined behaviour in C++11?
Is it legal to write to std::string?
writing directly to std::string internal buffers
.. in C++11 it should be possible to call a C API function which takes a char pointer to store the output like this:
str::string str;
str.reserve(SOME_MAX_VALUE);
some_C_API_func(&str[0]);
But is there now a legal way to set the size of the string to the length of the (null terminated) content inside the buffer? Something like this:
str.set_size(strlen(&str[0]));
This is a very unaesthetic abuse of std::string anyway I hear you say, but I can't create a temporary char buffer on stack so I would have to create a buffer in heap and destroy it afterwards (which I want to avoid).
Is there a nice way to do this? Maybe not reserving but resizing and calling erase() afterwards would do it but it doesn't feel nice neater..
You should be using resize() not reserve(), then resize() again to set the final length.
Otherwise when you resize() from zero to the result returned by strlen() the array will be filled with zero characters, overwriting what you wrote into it. The string is allowed to do that, because it (correctly) assumes that everything from the current size to the current reserved capacity is uninitialized data that doesn't contain anything.
In order for the string to know that the characters are actually valid and their contents should be preserved, you need to use resize() initially, not reserve(). Then when you resize() again to make the string smaller it only truncates the unwanted end of the string and adds a null terminator, it won't overwrite what you wrote into it.
N.B. the initial resize() will zero-fill the string, which is not strictly necessary in your case because you're going to overwrite the portion you care about and then discard the rest anyway. If the strings are very long and profiling shows the zero-filling is a problem then you could do this instead:
std::unique_ptr<char[]> str(new char[SOME_MAX_VALUE]);
some_C_API_func(str.get());
This was/is a known limitation of C++ until C++20.
From C++23 you can use resize_and_overwrite():

assigning one shared_ptr to another

Does assigning one shared pointer to another free the memory managed by the latter? Let
typedef shared_ptr<char> char_ptr_t;
char_ptr_t pA(new char('A'));
char_ptr_t pB(new char('B'));
Now, does the below statement free the memory of 'A'?
/*1*/ pA = pB;
Or do I need to explicitly free it:
/*2*/ pA.reset();
/*3*/ pA = pB;
And, is the following code valid for achieving the same?
/*4*/ pA.reset(pB); //<-- is this valid? Not compiling in MSVC++ 2010, though the standard seems to allow it.
Yes, pA does not point to the char 'A' anymore, so the reference count is decremented. As it was the only reference to 'A', the reference count reaches zero and the char is deleted. It would be highly surprising and error-prone if you'd have to explicitly release the reference before reassignment.
pA.reset(pB) should not compile, as reset can only take a raw pointer, not another shared_ptr.

What does Arduino's "F()" actually do?

I have asked a similar question before, but I realize that I can't make heads or tails of the macrology and templateness. I'm a C (rather than C++) programmer.
What does F() actually do? When does it stuff characters into pgmem (flash)? When does it pull characters out of pgmem? Does it cache them? How does it handle low-memory situations?
There are no templates involved, only function overloading. The F() macro does two things:
uses PSTR to ensure that the literal string is stored in flash memory (the code space rather than the data space). However, PSTR("some string") cannot be printed because it would receive a simple char * which represents a base address of the string stored in flash. Dereferencing that pointer would access some random characters from the same address in data. Which is why F() also...
casts the result of PSTR() to __FlashStringHelper*. Functions such as print and println are overloaded so that, on receiving a __FlashStringHelper* argument, they correctly dereference the characters in the flash memory.
BTW. For the ESP32 library, both of these functions are defined in the following files:
# PSTR : ../Arduino/hardware/espressif/esp32/cores/esp32/pgmspace.h
# F : ../Arduino/hardware/espressif/esp32/cores/esp32/WString.h
And the F(x):
// An abstract class used as a means to provide a unique pointer type
// but really has no body
class __FlashStringHelper;
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
...
Also for ESP32, PSTR(x) is not needed and is just x: #define PSTR(s) (s).

Understanding MAKEINTRESOURCEW definition

Looking at the Windows SDK, I found this #define directive for MAKEINTRESOURCEW:
#define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i))))
Can someone explain to me what the heck that means? For example, what would be the value of MAKEINTRESOURCEW(0)? (1)? (-1)?
The result of this macro will be pointer to long string with value equal to given parameter. You can see it by reading precompiler output (see /P C++ compiler options). All casting is required to compile this macro result, when LP[w]WSTR pointer is required, both in Win32 and x64 configurations.
Some Windows API, like LoadIcon, expect string pointer as their parameter. Possibly, these functions test the pointer value, and if it is less than some maximum, they interpret it as resource index, and not as string (problems of ugly C-style interface). So, this macro allows to pass WORD as string, without changing its value, with appropriate casting.
For the most part, it leaves the value unchanged, but converts it from an int to a pointer so it's acceptable to functions that expect to see a pointer. The intermediate casts widen the input int to the same size as a pointer, while ensuring against it's being sign extended. In case you care, ULONG_PTR is not a "ULONG POINTER" like you might guess -- rather, it's an unsigned long the same size as a pointer. Back before 64-bit programming became a concern, the definition was something like:
#define MAKEINTRESOURCE(i) (LPTSTR) ((DWORD) ((WORD) (i)))
Nowadays, they use ULONG_PTR, which is a 32-bit unsigned long for a 32-bit target, and a 64-bit unsigned long for a 64-bit target.
That's a macro that casts an argument i to a word, then casts that result to a pointer to an unsigned long, then again to a long pointer to a wide-character string.
Like other users said - it just casts an integer into a "pointer to a string".
The reason for this is the following: At the ancient times of Windows 3.0 people tried to be minimalistic as much as possible.
It was assumed that resources in the executable can have either string identifier or integer. Hence when you try to access such a resource - you specify one of the above, and the function distinguish what you meant automatically (by checking if the provided "pointer" looks like a valid pointer).
Since the function could not receive a "variable argument type" - they decided to make it receive LPCTSTR (or similar), whereas the actual parameter passed may be integer.
Another example from Windows API: A pointer to the window procedure. Every window has a window procedure (accessed via GetWindowLong with GWL_WNDPROC flag.
However sometimes it's just an integer which specifies what "kind" of a window is that.
Then there's a CallWindowProc which knows to distinguish those cases.

Resources