Let's start with the fe_addDebugString function. If the debugtxt is an array of std::string then it's OK but if it's an array of char pointers - I suspect it is - then this instruction:
debugtxt[currdebug] = input;
stores only a pointer, it does not copy the string. That's why the content gets destroyed when you delete[] the original pointer after using the function.
I mentioned that copying the string with strcpy before passing it to the function would not be necessary, but it would be necessary inside the function, if you want to store it. But for that, each slot of the debugtxt array must point to a valid, allocated char buffer.
Now about the new FESTRING class. There is still a memory leak in that, because every time the convert2Char function is called, you allocate a new string without deleting the previous one. To use that class without memory leak, every time you want to convert something, you have to construct the class, then destroy it after use, instead of being able to construct it once and call convert2Char repeatedly for different strings.
Another problem is that the pointer = "" in the constructor does not mean that the pointer is "empty". It means that the pointer is valid but points to an empty string (which is located in your program text). The way to create an empty pointer is to set it to zero, meaning it points to nothing. (It's good to know that it is always safe to delete[] a zero pointer.)
The way to solve the problem is either to include delete[] into the convert2Char function before allocating the new string, or to allocate the string in the constructor once and for all, but then you have to estimate the maximum string length you are going to need.
To be honest, I don't understand why you are desperately trying to force this conversion and store the result. My general advice, which would be a solution to all your problems: keep your strings always in std::string format and do not convert them until the very last moment when you absolutely have to. When you need to pass an std::string to a Dark GDK function which expects a char pointer, it is very easy to include the c_str() into the function call, without storing the conversion result. This is a small price to pay for keeping the rest of the code simple, clean and (mainly) memory-safe. Take your test code above, it can be written without any conversion function, and shorter:
#include "DarkGDK.h"
#include <string>
using namespace std;
void DarkGDK ( void )
{
dbSyncOn ( );
dbSyncRate ( 0 );
string a = "hello";
dbPrint((char*)a.c_str());
while ( LoopGDK ( ) )
{
dbSync ( );
}
return;
}
The (char*) typecast shortens the typing, the official version would be the const_cast recommended by dark coder above, but this works as well.
One more small thing. Notice that in the code above I changed the include "string.h" to include <string>. Usually you should use this "new style" include, without extension and with < these brackets, whenever the compiler allows it. Omitting the extension means C++ header, and the < brackets mean this file should be searched first in the system directories. With "" the file is searched in your program directory first where your own source code files are.