How to convert string to char* and pass it without it getting deleted on the stack

This code gives me the output:
taco
 ╠╠╠╠╠╠╠╠
How can I make the second cout work? Pretend that main is a console and gmc is a dll.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  #include <iostream>
#include <string>
using namespace std;

void gmc(const char* name[])
{
	string food = "taco";
	name[0] = food.c_str();
	cout << name[0]<<endl;	
}

int main()
{
	const char* name[1];
	gmc(name);
	cout << name[0];
	
	return 0;
}
Last edited on
What do you think the value of name[0] is? What memory do you think that's pointing to? What do you think will be the result of trying to write data to that memory?

This is really no different to the problem you asked about in your other thread. If you want to copy data into name[0], you need to make sure that pointer is actually pointing to memory you've assigned to store that amount of data, either on the stack, or dynamically allocated on the heap.


EDIT: My apologies, I misread the code you posted.
Last edited on
How would I go about doing this with the char**? Note that I'm converting from a string to a char** because i'm building a bridge to connect c++ code to g2 (ik, pretty random).
you need to make sure that pointer is actually pointing to memory you've assigned to store that amount of data

At the point of the assignment (line 8), the memory is present and properly allocated. The problem is that the memory was allocated by local variable food (line 7). When gmc exits, food is destroyed and its destructor deallocates the memory. So by the time line 16 executes, the name[0] points to deallocated memory. Trying to access it produces undefined behavior.
Note that I'm converting from a string to a char**

No, you're converting a string to a char*. There's a difference. You're then storing that char* in an array, for some reason. But, even once you get this right, name isn't a string, it's an array of strings.

The point is that name is an array of pointers. A pointer is just a number, and that number is a memory address. But just because you have a memory address, doesn't mean that you can just write data to that address, because for all you know that memory is being used for something important, if you're lucky.

In your code, not only have you not allocated memory, you haven't even given the char* pointer in the array any value it all. The value is completely random.

In your code, at line 8, you're setting the value of name[0] to be the pointer returned by food.c_str(). However, that points to memory managed by food; when food is destroyed, that memory is freed up, so name[0] now points to invalid memory.

You need to make sure name[0] points to memory that's going to persist after the function exits. Which means you need to allocate that memory yourself.

EDIT: If the things I'm saying don't make any sense to you, then I suspect it's because you've never really learned about pointers, or about memory allocation. In which case, the best thing you can do is go back to your textbook and read those chapters.
Last edited on
At the point of the assignment (line 8), the memory is present and properly allocated.

Yeah, sorry - I misread the original code. Thanks for picking me up on that!
No, you're converting a string to a char*
- good catch
You're then storing that char* in an array, for some reason
- in my real code there are mulitple different arrays of strings that I am converting to char*'s and sending back.

Where would I need to allocate memory? The hard part is once I get the information into "main" I will need to send it to a different program in g2. For this conversion i'm pretty sure I can only send back void*'s. Does this mean I would need to allocate memory in my g2 program?
(g2 is a very obscure language that I'm being forced to use, the only thing I know about it so far is that it's a terrible language to learn/use lol)
Last edited on
Where would I need to allocate memory?

That's really a design question - you need to find the answer that best fits the design of your actual code.

I mean, in the sample code you posted (and well done for making the effort to post a minimal example that demonstrates the problem - that really helps us!) I would allocate it dynamically at line 8, and copy the contents of the array pointed to by food.c_str() into the memory I've just allocated.

But for your actual project - which, I assume, is much bigger than this - that might not be the best fit. That's a decision you'll have to make.

Actually, I wouldn't convert to a char* at all at that point. I'd use std::string as much as I possibly could. I'd make sure it was std::strings that were being passed back to main, and stored in main.

I'd only convert to a char* at the point where it was actually needed - i.e. at the point where it was passed to the library that required it.

But, again, I can only see your simple example. That may not be the most appropriate way of doing it for your actual project.

EDIT: What do you mean by "a different program in g2"? What's "g2"? Do you actually mean an entirely separate program, running in its own process? If so, what are you using to send data from one process to another?

OK, I can see you edited your post to explain that. I know nothing about this g2, so I have no idea how memory is managed in that language.
Last edited on
void * is generally just a transport mechanism. That is, you have a real pointer of a real type in hand, and some function out there accepts void pointers (and sometimes, a what is it field, other times, not). So your code has a char *, and you just pass that to the target and it accepts it into the void *. You don't have to DO anything here.

allocate memory in main.
ideally, you could use normal strings and just drop it to a C-string when you pass it back out to the g2. In that case, you might have a vector of string, which would get rid of any hands-on memory management.

if you want the DIY C solution, its something like this:

char ** names;
names = new char *[number_of_strings]
for(i = 0; i < number_of_strings; i++)
names[i] = new char[size_for_this_string_or_a_max_size_etc]

and deletion is reversed, loop first, then do the outer memory last.
for(...)
delete[] names[i];

delete[] names;

if you are going with a fixed width, you can also cheat into a single pointer.
char * cheat = new char[number of strings * fixed size]
access via cheat[string number*fixed size]
and it will work with less aggravation.







Do you actually mean an entirely separate program, running in its own process? If so, what are you using to send data from one process to another?
- yes, the language g2 provided a bridge that I have to use to send data back and forth. In my simplified code, "main" represents this the bridge and gmc is the lib that it talks to. In the actual bridge I will call a pre-made function like suchgsi_rpc_return_values(outConstraintNames, 12, call_handle, gsi_current_context()); where outConstraintNames is one of my char**'s in the form of a void* in order to return data to the g2 program.
Last edited on
char ** names;
names = new char *[number_of_strings]
for(i = 0; i < number_of_strings; i++)
names[i] = new char[size_for_this_string_or_a_max_size_etc]

//fill names array
//send off names array to g2

delete[] names[i];

delete[] names;

So do you think this would work? Or would g2 most likely loose the contents of names after it gets deleted.
It will work, but, seriously, use std::vector and std::string as much as you possibly can. Why make this harder on yourself?

Each process will have its own area of memory, entirely separate from the other. Freeing up memory in one process won't have any impact on what happens in another.

(Unless there's any weird, inter-process memory sharing mechanism you haven't told us about. But if that were the case, you wouldn't just be using standard memory allocation and primitive types.)
Last edited on
seriously, use std::vector and std::string as much as you possibly can
- I know, the problem is that the bridge only lets me use int's,char's, and void*'s.

Thanks for all the help guys! I really appreciative it, this forum is great!
I don't know *anything* about g2, as of 2 or 3 hours ago I didnt know it existed.

that aside, here is the problem.
you are, from the sound of it, trying to send a ** to another process. That process *cannot* use this memory unless it is shared between the two processes (if it is a library call, the memory is all in your process space and its fine, if its a totally separate program, its not fine). You may need to wrap the pointer code I gave you into some sort of shared memory space. How you do that depends a bit on your OS and libraries but shouldnt be too difficult. So while what I gave you is correct, you may need another step to deal with the interprocess part, depending on exactly what you are doing.

The good news is that if this is a problem, it will tell you in pretty clear terms: ACCESS VIOLATION Process XYZ tried to access memory location BLAHBLAHBLAH or words to that effect.

Last edited on
Without knowing anything about g2, it sounds as though there's some kind of C++ interface library that the OP is using - the "bridge" they mentioned. I'm guessing that library takes void* pointers in its API, and handles the messy business of passing the actual data over to the g2 process.

At least, I'd hope so :)
Topic archived. No new replies allowed.