-2

I'm wondering what happens to wchar_t* pointer after being used by WM_SETTEXT.

wchar_t* f = L"test1";
    wchar_t* f2 = L"test2";
    SendMessage(hWndEdit1, WM_SETTEXT, 0, (LPARAM)f);
    // after some operations 
    SendMessage(hWndEdit1, WM_SETTEXT, 0, (LPARAM)f2);
    delete f; // crashes

Why delete f; crashes?

Mesut
  • 1,845
  • 4
  • 24
  • 32
  • 1
    Why do you think you could delete something, that was never new'd? –  Jan 08 '18 at 13:24
  • 2
    You `delete` what you `new`, and `delete[]` what you `new[]`. If you haven't allocated anything with `new` or `new[]`, then you should not `delete` or `delete[]` it. – Some programmer dude Jan 08 '18 at 13:25
  • 1
    You also should avoid discarding `const` even if your compiler tries to let you. A literal like `L"test1"` is `const` so `f` and `f2` should also be `const`. – Dark Falcon Jan 08 '18 at 13:26
  • A similar question asked recently: [Should I delete pointers that come from other functions or class methods?](https://stackoverflow.com/questions/48151025/shoud-i-delete-pointers-that-come-from-other-functions-or-class-methods) – Bo Persson Jan 08 '18 at 13:48
  • When you pass a pointer through the `WM_SETTEXT` message, the system makes a copy of the contents. You can dispose of the pointee as soon as the `SendMessage` call returns. In this case, you are holding a pointer to a character array. The lifetime is controlled by the compiler; you need not do anything to clean up. – IInspectable Jan 08 '18 at 14:01

1 Answers1

1

You should remove this statement:

delete f; // crashes

You are causing undefined behavior by calling the delete operator on a pointer that was not new-ed. You should only delete what you new-ed and delete[] what you new[]-ed. Excerpt from the n4140 draft, paragraph 5.3.5.2:

the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8) representing a base class of such an object (Clause 10). If not, the behavior is undefined

Note that in standard C++ you should apply a const qualifier when using pointers to string literals:

const wchar_t* f = L"test";

Or even better use the wide string:

std::wstring ws = L"test";
Ron
  • 14,674
  • 4
  • 34
  • 47
  • doesn't it occupy memory on ram? So aren't we have to delete? – Mesut Jan 08 '18 at 13:31
  • 1
    Sure, it occupies memory. But you can only `delete` something that was allocated using operator `new`. Using `delete` on anything else doesn't work. Why? Because that's that the C++ standard specifies. – Peter Jan 08 '18 at 13:38
  • You may find this helpful... https://stackoverflow.com/questions/36646493/c-stack-vs-heap-allocation – franji1 Jan 08 '18 at 13:58
  • @Peter, If so, automatically deallocate at the end of the scope? – Mesut Jan 08 '18 at 14:03
  • 1
    No. It doesn't. Typically the memory for those literals will be static and deallocated when the program terminates. They were allocated when the program started. – David Heffernan Jan 08 '18 at 14:05
  • 1
    @Mesut: [String literals](http://en.cppreference.com/w/cpp/language/string_literal) have static storage duration. They live for the entire lifetime of your program. – IInspectable Jan 08 '18 at 14:06
  • I'd like to allocate new pointer with "new" for wchar_t array and "delete" after SendMessage(). How to do this according to my sample? – Mesut Jan 08 '18 at 18:04
  • 1
    @Mesut: Don't. Use a `std::wstring` instead: `std::wstring ws{ L"test" }; ::SendMessage( hWndEdit1, WM_SETTEXT, 0, (LPARAM)ws.c_str() );`. There is no reason to use `operator new` and `operator delete` in C++. Why do you want to resort to manual memory management? – IInspectable Jan 08 '18 at 18:23
  • @IInspectable: 1. I think that wchar_t is faster than std::wstring. I'll perform long long operations. 2. I'll compile my dll for both windows and linux and want to be used by C++ core functions not by extended libraries. Am I wrong? – Mesut Jan 08 '18 at 19:01
  • @Mesut: Yes, you are wrong. The expensive operation is `operator new`. It doesn't matter, whether you use a raw array, or `std::wstring`, where the latter can actually be faster in subsequent operations, because it doesn't have to calculate the string length. Don't neglect the first rule of performance optimization: Do not make any assumptions. Profile your code instead. I'm not sure what your second point is supposed to mean, but `std::wstring` is standard C++. You will not get any better in terms of interoperability than using the standard. As long as you get the ABI issues sorted out. – IInspectable Jan 08 '18 at 19:12