Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I was practicing C++ and find this task in the web. The question in of task is "What is the wrong with this code?"
#include <iostream>
void StrIn(char *sp)
{
sp = new char[256];
sp[0] = '1';
sp[1] = '2';
sp[2] = '\0';
}
int main()
{
char *pt=0;\\ something wrong here
StrIn (pt);
std::cout << pt[1];
delete[] pt;
return 0
}
First of all. I do not understand why StrIn do not changes values of elements pt[].
Second. Why program shouts down when
char *pt=0;
and works "fine" with
char *pt;
Obviously I do not understand something but I spend 4 hours on this task and don't get any closer to solution so asking you for help.
UPD:
Why the output for
std::cout << pt;
ending with "-" symbol and shows only sevral symbols inicializated in a row?
You're passing the pointer by value, so inside the function you're actually assigning to a new pointer, not the original one.
Change the function prototype to void StrIn(char *&sp).
The equivalent for your code with an integer:
#include <iostream>
void ReadInt(int i)
{
i = 2;
}
int main()
{
int i = 0;
ReadInt (i);
std::cout << i;
return 0
}
The problem here is that your are passing a copy of i, and changing it in ReadInt does not change the int in main.
There are 2 solutions:
Solution 1
Return the changed number:
int ReadInt()
{
return 2;
}
int main()
{
int i = 0;
i = ReadInt();
std::cout << i;
return 0
}
In your case:
char* StrIn()
{
sp = new char[256];
sp[0] = '1';
sp[1] = '2';
sp[2] = '\0';
return sp;
}
int main()
{
char* pt = 0;
pt = StrIn();
std::cout << pt[1];
delete[] pt;
return 0;
}
Solution 2
Pass the reference, or memory location of your variable.
For integer:
void ReadInt(int& i) which would be called like this: ReadInt(i)
//or
void ReadInt(int* i) which would be called like this: ReadInt(&i)
In your case:
void StrIn(char*& sp) which would be called like this: StrIn(pt)
//or
void StrIn(char** sp) which would be called like this: StrIn(&pt)
To get data that a double pointer points to you need to dereference the pointer.
char* deref = *(double_pointer);
I do not understand why Str do not changes values of elements pt[].
When Str is called, the value of pt is passed to it. pt is a pointer, so the value is an **address*. You are passing an address to Str. So far, so good.
Now in Str, what happens? You take your copy of the address, call it sp and immediately replace it with a new address (the one returned by new). All subsequent code in Str only modifies what is pointed at by that new address. The original address is untouched.
Then Str returns, the copy is discarded, and what was pointed at by the copy is left in memory forever (until the program ends).
The rest of the program deals with the original address.
Why program shouts down when char *pt=0; and works "fine" with char
*pt;
It's just undefined (i.e. more or less random) behaviour in both cases. In main, you use the original address, regardless of what happens with the copy in Str. A 0 address is not valid for the [] operation, neither is using an uninitialised variable.
The only real difference is with delete[], which will work fine by doing nothing with a null pointer and yield undefined behaviour with an uninitialised variable.
Obviously i do not understand somthing but i spend 4 hours on this
task and dont get any closer to solution so asking u for help.
You are mistaking real strings with char arrays or pointers (i.e. memory addresses).
In C++, when you need strings, use the std::string class and everything will work as expected.
When you use char arrays or pointers, you need to learn a lot more about language details. Start with a good tutorial or a good book. Some hours are not enough, but some days should suffice.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am trying to return a char array in C++ using a getter function. This is academic and we are required to use char[]/char*, and then return it so we can cout the array to the console.
char* Groceries:: getList() const
// Returns the list member.
{
return list;
}
I have also trying using strcpy in that function. Both methods return what seems to be a memory location when I use cout which resembles something like: "ám♥". If i try to perform: cout << glistone.getList()[0]; it just returns the first character in the the previous line: "ám♥".
I have read many, many SO questions on C Strings, etc., but none of the accepted solutions seem to do anything when I build/run my program other than return what I'm already returning.
How can you return a char* in C++, print it out, and not return the memory address?
Here is an example of a function that returns a C-Style string and the main function that prints it.
#include <stdio>
char * a_function(void)
{
static const char my_test[] = "Propane explodes.\n";
return &my_test[0]; // It's a MISRA thing.
}
int main(void)
{
char * p_text = 0;
p_text = a_function();
std::cout << Here's the text: "
<< p_text;
std::cout.flush(); // Just to be sure.
return 0;
}
In your function, I recommend you use a debugger and verify the value of list.
The example above uses hard-coded char arrays, to prove the concept. You have a variable, which we don't know the type, nor do we know how it gets its value, so YOU will have to discover it's contents. Debuggers can help you with this.
Edit 1
For the purists, I know that the function should return a char const *, but I wanted to match the OP's function, but using constant data.
Here's another version of the function:
char * another_function(void)
{
static char text_buffer[64];
strcpy(text_buffer, "Use a debugger!\n");
return text_buffer;
}
If you are absolutely required to use a C-style array and pointers, then you need to use new, and preferably smart pointers:
std::unique_ptr<char[]> getList() const {
const char *someCString = // whatever
char *p = new char[strlen(someCString) + 1];
strcpy(p, someCString);
return std::unique_ptr<char[]>(p);
}
and in the caller:
auto p = object.getList();
std::cout << p.get() << "\n";
If you can't use smart pointers either, then delete[] the returned pointer in the caller when it's not used anymore, so as to free the memory.
The problem has nothing common with the function definition though its return type could be defined as const char *
The problem is that the string that is stored in or pointed to by list is not zero terminated and it seems contains some garbage.
So search the error where you are modifying list.
Also your question
How can you return a char* in C++, print it out, and not return the
memory address?
is contradictory. If list is defined as an array you could return a reference to this array instead of the pointer if you do not want to return the pointer.:)
This question already has answers here:
Do pointers to string literals remain valid after a function returns?
(4 answers)
Closed 8 years ago.
Although the following code does work, I do not know why. Please explain me.
#include <iostream>
using namespace std;
const char *f()
{
const char *p = "Hello!\n";
return p;
}
int main()
{
cout << f() << endl;
system("pause");
return 0;
}
From what I learnt, the 7 chars in f() are allocated on the stack (?), meaning that their memory will be released as soon as f() ends, however, the pointer returned by f() still points to a valid address in the application memory (meaning "Hello!" is successfully sent to the output). Why?
Same thing goes for
const int *f()
{
int i = 5;
const int *p = &i;
return p;
}
int main()
{
cout << *f() << endl;
system("pause");
return 0;
}
Can anyone shed some light on this?
What you´ve learned is correct, it´s not allowed to use local function variables
(ie. their used memory) anymore after the function ends.
If it works currently it´s nothing more than coincidence:
No other code has used this piece of memory in the meantime
for own things, so the old value is still there.
Your second code snippet causes undefined behaviour. The reason why it seems to work is, that you are lucky and the memory has not been overwritten.
However (as in the comment below mentioned) the first snippet is valid.
I'm trying to initialize the values of an object, then pass it into a function, but visual studio tells me at this point that my two variables (question and answer) inside my object have "bad pointers" and cannot be evaluated. Unfortunately, I need to access both later on.
I've tried displaying question[i] and answer[i] right before calling enqueue() and it echoes correctly.
It's as if when I call the enqueue() function it doesn't remember what values I gave the card object when I called the constructor right before.
I'm not sure why my code breaks here, do I need to make a dynamic object?
card::card(char *q_input, char *a_input)
{
char * question = new char [75];
char * answer = new char [25];
strncpy(question,q_input,strlen(q_input)+1);
strncpy(answer,a_input,strlen(a_input)+1);
}
...
int queue::fill_deck(char **question, char **answer)
{
for(int i = 0; i < 9; i++)
{
card Card(question[i],answer[i]);
enqueue(Card); //ERROR!
}
return 0;
}
Thank you for the help!
Please let me know if you need more information.
EDIT: the problem was that I was redeclaring two variables with my constructor. A syntax mistake on my part!
One huge issue: This code does nothing except cause a memory leak:
card::card(char *q_input, char *a_input)
{
char * question = new char [75];
char * answer = new char [25];
strncpy(question,q_input,strlen(q_input)+1);
strncpy(answer,a_input,strlen(a_input)+1);
}
question and answer are local variables. Not only that, you then allocate memory and assign the returned pointer to these local variables. When that function exits, those locals go away, plus any chance of deallocating the memory you allocated goes away with it, causing a memory leak.
Before doing anything else, why are you using new[] instead of std::string? You tagged this as C++, but all of your coding is 'C'.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 8 years ago.
char* func()
{
const int size = 24;
char bin[size];
char *temp;
for(int i=0; i<23; i++)
bin[i] = '1';
bin[23] = '\0';
temp = bin;
return temp;
}
int main()
{
char *s;
s = func();
cout << s << endl; //prints out weird values
return 0;
}
When compiled and ran, it print random values. In the function func, I initialized a char array and tried to return it. Upon returning it and printing it in main, it prints out weird values. What is wrong? Any help would be appreciated.
char bin[size];
allocate memory on the stack, you cannot refer to that location after the function returns: "char *s" is assigned a value that refer to an invalid memory location.
You must not use pointers to freed space, like the stack of a function which has finished executing.
This Undefined Behavior means anything goes, even the proverbial demons flying out of your nose.
Your choices:
Use a caller-allocated buffer.
Use a static buffer (beware reentrancy problems and multithreading woes).
Use dynamic allocation (new, new[], malloc() and friends).
return a struct (standard container or otherwise) containing the data. Might use dynamic allocation. (Last point courtesy of Matt McNabb).
I am currently working my way through C++ Primer Fifth Edition. I have gone through a couple of other C++ books, but they weren't very detailed and were quite complicated.
This book has been helping me a lot with everything that I have missed. I've just hit a wall.
One of the exercises asks me to write a declaration for a function that returns a reference to an array of ten strings, without using trailing return, decltype, or type alias.
I know it only says write a declaration, which I have done, like so:
string (&returnArray()) [10];
I wanted to write a function definition as well, like so:
string (&returnString(int i, string s)) [10]
{
string s1[10];
s1[i] = s;
return s1;
}
In my main function, I have a for loop which passes a string literal through and stores that string inside a pointer to an array of ten strings. It should then output the results to the screen.
The problem I am having is, when I dereference my pointer to an array, once, it will output the address. If I dereference it twice, the program outputs nothing and stops responding.
Here is my main function, I have changed it multiple times, yet can't figure out why it's not outputting properly. I've probably got it all wrong...
int main()
{
string (*s)[10];
for(int i = 0; i != 10; ++i)
{
s = &returnString(i, "Hello");
cout << s[i] << endl;
}
return 0;
}
Your function returns a reference to a local variable – after the call, it’s a dangling reference. You cannot do that.
You can only return references to storage that goes on existing after the end of the function call.
Returning a reference to a temporary local object invokes undefined behavior.
A short fix is making it static:
string (&returnString(int i, string s)) [10]
{
static string s1[10];
^^^^^^
s1[i] = s;
return s1;
}
int main()
{
string(&s)[10] = returnString(0, "Hello");
for (int i = 0; i != 10; ++i)
{
s[i] = "Hello";
cout << s[i] << endl;
}
}
Returning pointers/references to local variables is bad, undefined behavior. You can follow your exercise and not forget that constraint, your exercise tells you to do something but it's not necessarily telling you to do it the wrong way, in fact it's a good one that will lead you to pitfalls and hence make you a better programmer once you figure them out.
So what's left given that constraint of not returning addresses to local variables but still addressing the task given? You have the static fix as M M. already mentioned, or you could think you're creating something useful like a function rotate, for example, that accepts an string(&)[10] and returns itself rotated ;-)
Look that, iostream insertion and extraction operators already work like that, returning references to parameters passed by reference.