Page 1 of 1

Getting a weird string return

Posted: Sat May 13, 2017 3:11 am
by LunaRebirth
I'm going to make this as short as possible, but it's been stressing me out for the last 12 hours.

Basically I'm reading content from a file to run as a lua script.
For each script, there is a new LuaScript() object created.
The jist of what I'm doing is absolutely nothing new, and pretty basic, so I don't understand why I'm having issues.

When I use lua to run LuaScript[x]->getCont() (Runs the content of the lua file), it runs fine with no issues.
But when I do something like a print statement using LuaScript[x]->getCont(), I'm given a piece of the content, with nothing else in the print.

For example,

Code: Select all

printf("This text isn't appearing. This content is cut into a piece: %s\n", script[0]->getCont());
Pretending that content holds "test", the output would be:
"te"
even without the beginning part of the printf statement.

I don't understand what's going on as this is a new issue I have never encountered.
I've change LuaScript's cont variable to be a char* and an std::string with no change in results.

The weird thing is that running the Lua using getCont() uses the entire correct content. But using getCont() to print it does not work.
It also does not work while trying to send the getCont() to a server with send(), which is what I'm trying to use it for.

Anyone have any explanations as to why this might be happening?

Re: Getting a weird string return

Posted: Sat May 13, 2017 9:23 am
by CuteAlien
Never had that. What does it show in memory when you set a breakpoint there? Do you maybe use printf in several threads? It's not thread-safe, so you have to use mutexes around it when doing that.

Note that if your code overwrites memory at some place all kind of effects can happen. Hunting such a bug is harder. Usually you have to use divide&conquer - splitting your application up into smaller and smaller parts and testing each of those on their own until you located the problem. Or on Linux you can use a tool like Valgrind to see if it catches any errors.

Re: Getting a weird string return

Posted: Tue May 16, 2017 4:45 pm
by LunaRebirth
Still can't figure it out. Everything seems fine except that I can't send it and can't print it. Using an if statement to compare it to what the content should be works fine.
Not overwriting any memory. Seems like an issue beyond my written code.
Looks like I'll redo some stuff and find a different way to get the results I'm looking for.

Re: Getting a weird string return

Posted: Sat May 20, 2017 1:56 am
by LunaRebirth
Turns out the problem is something I can't find on Google, though I didn't try for long.
If I make a const char* and assign a value, then make a string and assign it to the const char*'s value, it sometimes messes up.
Just an example, not real data:
const char* info = "aaaa"
std::string otherInfo = info

otherInfo then holds something like "???a???aaa"
(replacing ??? with random looking symbols)

Has anyone else experienced this?

Re: Getting a weird string return

Posted: Sat May 20, 2017 7:43 am
by hendu
That's not possible. You have corrupted software or hardware.

Re: Getting a weird string return

Posted: Sat May 20, 2017 11:08 am
by CuteAlien
If that's your complete code - then yeah - like hendu said - that shouldn't be. But more often when mixing pointers and string-classes the user messes up somewhere. Examples: You return a pointer to some string you created dynamically (like return std::string("bla").c_str() for a local string - that even might look like works as memory is often still there... but then your next function returns that pointer - and then you start to notice you got corruption). Or you return a pointer to a static string somewhere which buffers stuff, but you overwrite that static at some point. Then your string can look pretty much like your string (this happened to me just last week *sigh*).

What I'm trying to say - when string-pointers look like that it's nearly always a life-time thing - you are having pointers to strings which are no longer valid at this point.

Re: Getting a weird string return

Posted: Mon May 22, 2017 3:36 pm
by LunaRebirth
Ah that could quite possibly be it. I was able to fix my getCont() function and stop the issue by creating a local variable that holds the content, then returns it. But returning the content directly is what was giving the corruption.
Seems I've found a second spot where this is occurring. Quite annoying.

Re: Getting a weird string return

Posted: Mon Jun 12, 2017 2:50 am
by LunaRebirth
I am having this problem reoccur more often than it should.
Code as simple as

Code: Select all

char* addMediaPath(std::string dir) {
  if (dir.find("media/") != 0) {
    dir = "media/" + dir;
  }
  char* newDir = (char*)dir.c_str();
  return newDir;
}
If I call addMediaPath("media/file.txt"), I'll get some crazy result like binary-looking letters.
But it doesn't happen every time, yet it happens enough to notice that this function is creating the issue.

I'm wondering if this has to do with memory management at all. Can memory leaks cause this sort of thing? I don't see anything wonky from looking at the usage in task manager.

Edit:
I have checked variables before and after using this function.
It is for sure coming from here in my code.

Re: Getting a weird string return

Posted: Mon Jun 12, 2017 9:02 am
by hendu
You can't do that. You really need to read up on the C++ classes you use, those are beginner-level mistakes and you keep making the same ones, repeatedly.

Re: Getting a weird string return

Posted: Mon Jun 12, 2017 10:12 am
by CuteAlien
To explain some more. "dir" is on the stack. That memory will be released as soon as the function has finished. Which means newDir now points to memory which is no longer valid. Anything can be written in there now (as you can see by the mess you get).

If you need to return that string you _must_ copy it. Either by returning it inside a string class like std::string (which will internally copy the string and returned variables are always on the stack of the caller function), or by creating an explicit copy the c-way (not recommended usually, something like: myVar = new char[dir.size()+1], strncpy(myVar, dir.c_str(), dir.size()+1] ... but you don't need it). C-style also means you must free the memory again when you no longer need it (hm, nice part about C is - it's pretty explicit - you learn fast that all memory _must_ be copied manually as no classes ever do that for you ^_^).

If you need to pass raw-pointer to some other library - which is the main reason you generally need them - you can return a std::string in your function. And then pass the .c_str() of that result. Because the result of the function is in the scope of the caller function (as you can see by the fact that you can call .c_str() on the result from the caller function). And the std::string will create a copy internally.

In short: Whenever you work with raw-pointers in C++ - be aware if the memory they point to is really allocated. Either with new (and not yet deleted) or it's on the stack and (that's the important part!!!) the object will *stay* on the stack as long as you use that raw-pointer to it.

If "stack" and "heap" memory confuse you - read up on it on the web until they no longer confuse you. It's important in C++ and you only have to really understand it once and then it will no longer cause troubles.

Re: Getting a weird string return

Posted: Mon Jun 12, 2017 1:26 pm
by MartinVee
Architecturally speaking, is there a specific reason to accept a C++ string class as a parameter, but returning a C-style character pointer? Why not go all the way with std::string, while you're at it?

Re: Getting a weird string return

Posted: Mon Jun 12, 2017 3:21 pm
by LunaRebirth
Okay thanks for your help CuteAlien. Clearly I need to read up some more on stacks so I don't lose the memory.
hendu wrote:You can't do that. You really need to read up on the C++ classes you use, those are beginner-level mistakes and you keep making the same ones, repeatedly.
I learned C++ purely on my own Via Google :/ these must be mistakes that I never learned from because Ive never had them
MartinVee wrote:Architecturally speaking, is there a specific reason to accept a C++ string class as a parameter, but returning a C-style character pointer? Why not go all the way with std::string, while you're at it?
I thought it would be fine to do. The reason behind it is that writing a file takes a C-style character pointer, and it is easier for me to call addMediaPath("Servers/" + this->server + "/file.txt"); rather than making a local string and plugging in the c_str() of it. Through looking at the function code, this seemed like a good idea.