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'.
Related
i am stuck and unable to figure out why this is the following piece of code is not running .I am fairly new to c/c++.
#include <iostream>
int main(){
const char *arr="Hello";
const char * arr1="World";
char **arr2=NULL;
arr2[0]=arr;
arr2[1]=arr1;
for (int i=0;i<=1;i++){
std::cout<<arr2[i]<<std::endl;
}
return 0;
}
where as this is running perfectly fine
#include <iostream>
int main(){
const char *arr="Hello";
const char * arr1="World";
char *arr2[1];
arr2[0]=arr;
arr2[1]=arr1;
for (int i=0;i<=1;i++){
std::cout<<arr2[i]<<std::endl;
}
return 0;
}
Why is this? and generally how to iterate over a char **?
Thank You
char *arr2[1]; is an array with one element (allocated on the stack) of type "pointer to char". arr2[0] is the first element in that array. arr2[1] is undefined.
char **arr2=NULL; is a pointer to "pointer to char". Note that no memory is allocated on the stack. arr2[0] is undefined.
Bottom line, neither of your versions is correct. That the second variant is "running perfectly fine" is just a reminder that buggy code can appear to run correctly, until negligent programming really bites you later on and makes you waste hours and days in debugging because you trashed the stack.
Edit: Further "offenses" in the code:
String literals are of type char const *, and don't you forget the const.
It is common (and recommended) practice to indent the code of a function.
It is (IMHO) good practice to add spaces in various places to increase readability (e.g. post (, pre ), pre and post binary operators, post ; in the for statement etc.). Tastes differ, and there is a vocal faction that actually encourages leaving out spaces wherever possible, but you didn't even do that consistently - and consistency is universially recommended. Try code reformatters like astyle and see what they can do for readability.
This is not correct because arr2 does not point to anything:
char **arr2=NULL;
arr2[0]=arr;
arr2[1]=arr1;
correct way:
char *arr2[2] = { NULL };
arr2[0]=arr;
arr2[1]=arr1;
This is also wrong, arr2 has size 1:
char *arr2[1];
arr2[0]=arr;
arr2[1]=arr1;
correct way is the same:
char *arr2[2] = { NULL };
arr2[0]=arr;
arr2[1]=arr1;
char **arr2=NULL;
Is a pointer to a pointer that points to NULL while
char *arr2[1];
is an array of pointers with already allocated space for two items.
In the second case of the pointer to a pointer you are are trying to write data in a memory location that does not exist while in the first place the compiler has already allocated two slots of memory for the array so you can assign values to the two elements.
If you think of it very simplistically, a C pointer is nothing but an integer variable, whose value is actually a memory address. So by defining char *x = NULL you are actually defining a integer variable with value NULL (i.e zero). Now suppose you write something like *x = 5; This means go to the memory address that is stored inside x (NULL) and write 5 in it. Since there is no memory slot with address 0, the the entire statement fails.
To be honest it;s been ages since I last had to deal with such stuff however this little tutorial here, might clear the motions of array and pointers in C++.
Put simply the declaration of a pointer does NOT reserve any memory, where as the declration of a array doesn't.
In your first example
Your line char **arr2=NULL declares a pointer to a pointer of characters but does not set it to any value - thus it is initiated pointing to the zero byte (NULL==0). When you say arr2[0]=something you are attempting to place a valuei nthis zero location which does not belong to you - thus the crash.
In your second example:
The declaration *arr2[2] does reserve space for two pointers and thus it works.
I have a quick question regarding the scope of dynamic arrays, which I assume is causing a bug in a program I'm writing. This snippet checks a function parameter and branches to either the first or the second, depending on what the user passes.
When I run the program, however, I get a scope related error:
error: ‘Array’ was not declared in this scope
Unless my knowledge of C++ fails me, I know that variables created within a conditional fall out of scope when when the branch is finished. However, I dynamically allocated these arrays, so I cannot understand why I can't manipulate the arrays later in the program, since the pointer should remain.
//Prepare to store integers
if (flag == 1) {
int *Array;
Array = new int[input.length()];
}
//Prepare to store chars
else if (flag == 2) {
char *Array;
Array = new char[input.length()];
}
Can anyone shed some light on this?
Declare Array before if. And you can't declare array of different types as one variable, so I think you should use to pointers.
int *char_array = nullptr;
int *int_array = nullptr;
//Prepare to store integers
if (flag == 1) {
int_array = new int[input.length()];
}
//Prepare to store chars
else if (flag == 2) {
char_array = new char[input.length()];
}
if (char_array)
{
//do something with char_array
}
else if (int_array)
{
//do something with int_array
}
Also as j_random_hacker points, you might want to change you program design to avoid lot's of if
While you are right that since you dynamically allocated them on the heap, the memory won't be released to the system until you explicitly delete it (or the program ends), the pointer to the memory falls out of scope when the block it was declared in exits. Therefore, your pointer(s) need to exist at a wider scope if they will be used after the block.
The memory remains allocated (i.e. taking up valuable space), there's just no way to access it after the closing }, because at that point the program loses the ability to address it. To avoid this, you need to assign the pointer returned by new[] to a pointer variable declared in an outer scope.
As a separate issue, it looks as though you're trying to allocate memory of one of 2 different types. If you want to do this portably, you're obliged to either use a void * to hold the pointer, or (less commonly done) a union type containing a pointer of each type. Either way, you will need to maintain state information that lets the program know which kind of allocation has been made. Usually, wanting to do this is an indication of poor design, because every single access will require switching on this state information.
If I understand your intend correctly what you are trying to do is: depending on some logic allocate memory to store n elements of either int or char and then later in your function access that array as either int or char without the need for a single if statement.
If the above understanding is correct than the simple answer is: "C++ is a strong-typed language and what you want is not possible".
However... C++ is also an extremely powerful and flexible language, so here's what can be done:
Casting. Something like the following:
void * Array;
if(flag1) Array = new int[len]
else Array = new char[len];
// ... later in the function
if(flag) // access as int array
int i = ((int*)Array)[0];
Yes, this is ugly and you'll have to have those ifs sprinkled around the function. So here's an alternative: template
template<class T> T foo(size_t _len)
{
T* Array = new T[_len];
T element = Array[0];
return element;
}
Yet another, even more obscure way of doing things, could be the use of unions:
union int_or_char {int i; char c;};
int_or_char *Array = new int_or_char[len];
if(flag) // access as int
int element = Array[0].i;
But one way or the other (or the third) there's no way around the fact that the compiler has to know how to deal with the data you are trying to work with.
Turix's answer is right. You need to keep in mind that two things are being allocated here, The memory for the array and the memory when the location of the array is stored.
So even though the memory from the array is allocated from the heap and will be available to the code where ever required, the memory where the location of the array is stored (the Array variable) is allocated in the stack and will be lost as soon as it goes out of scope. Which in this case is when the if block end. You can't even use it in the else part of the same if.
Another different code suggestion from Andrew I would give is :
void *Array = nullptr;
if (flag == 1) {
Array = new int[input.length()];
} else if (flag == 2) {
Array = new char[input.length()];
}
Then you can directly use if as you intended.
This part I am not sure : In case you want to know if its an int or char you can use the typeid literal. Doesn't work, at least I can't get it to work.
Alternatively you can use your flag variable to guess what type it is.
I apologise if I'm completely misunderstanding C++ at the moment, so my question might be quite simple to solve. I'm trying to pass a character array into a function by value, create a new array of the same size and fill it with certain elements, and return that array from the function. This is the code I have so far:
char *breedMutation(char genome []){
size_t genes = sizeof(genome);
char * mutation = new char[genes];
for (size_t a = 0 ;a < genes; a++) {
mutation[a] = 'b';
}
return mutation;
}
The for loop is what updates the new array; right now, it's just dummy code, but hopefully the idea of the function is clear. When I call this function in main, however, I get an error of initializer fails to determine size of ‘mutation’. This is the code I have in main:
int main()
{
char target [] = "Das weisse leid"; //dummy message
char mutation [] = breedMutation(target);
return 0;
}
I need to learn more about pointers and character arrays, which I realise, but I'm trying to learn by example as well.
EDIT: This code, which I'm trying to modify for character arrays, is the basis for breedMutation.
int *f(size_t s){
int *ret=new int[s];
for (size_t a=0;a<s;a++)
ret[a]=a;
return ret;
}
Your error is because you can't declare mutation as a char[] and assign it the value of the char* being returned by breedMutation. If you want to do that, mutation should be declared as a char* and then deleted once you're done with it to avoid memory leaks in a real application.
Your breedMutation function, apart from dynamically allocating an array and returning it, is nothing like f. f simply creates an array of size s and fills each index in the array incrementally starting at 0. breedMutation would just fill the array with 'b' if you didn't have a logic error.
That error is that sizeof(genome); will return the size of a char*, which is generally 4 or 8 bytes on a common machine. You'll need to pass the size in as f does since arrays are demoted to pointers when passed to a function. However, with that snippet I don't see why you'd need to pass a char genome[] at all.
Also, in C++ you're better off using a container such as an std::vector or even std::array as opposed to dynamically allocated arrays (ones where you use new to create them) so that you don't have to worry about freeing them or keeping track of their size. In this case, std::string would be a good idea since it looks like you're trying to work with strings.
If you explain what exactly you're trying to do it might help us tell you how to go about your problem.
The line:
size_t genes = sizeof(genome);
will return the sizeof(char*) and not the number of elements in the genome array. You will need to pass the number of elements to the breedMutation() function:
breedMutation(target, strlen(target));
or find some other way of providing that information to the function.
Hope that helps.
EDIT: assuming it is the number of the elements in genome that you actually want.
Array are very limited.
Prefer to use std::vector (or std::string)
std::string breedMutation(std::string const& genome)
{
std::string mutation;
return mutation;
}
int main()
{
std::string target = "Das weisse leid"; //dummy message
std::string mutation = breedMutation(target);
}
Try replacing the second line of main() with:
char* mutation = breedMutation(target);
Also, don't forget to delete your mutation variable at the end.
I am writing a programm in C++. In my programm I need to create an array with dynamic size inside one function, but this array should be also accessable for other functions. I will not post here my code, just write one dummy example.
char *array;
void function_1() {
array = new char(3);
array[0] = "value 1";
array[1] = "value 2";
array[2] = "value 3";
}
void function_2() {
array[0] = "new value 1";
}
int main() {
function_1();
function_2();
delete[] array;
}
My question is: I am not sure, if the array will exist outside the function_1, where it was initialised, until I delocate a memory of array.
Or the array will have just a behaviour of local variable inside one function. What means, that the memory, which stores the array values, will be dellocated after the function is finished and the memory addresses of my array can be rewroten with something else later in my programm.
Thank you.
First, of course it will exist outside, that's all what dynamic allocation is about. Also, the variable itself is global. Also, it should be a char const** array; and the allocation should be new char const*[3] (note the square brackets). The const because you won't change the contents of the strings here.
Second, don't do that. Just put it in a class and use a std::vector!
#include <vector>
class Foo{
public:
function_1(){
_array.push_back("value 1");
_array.push_back("value 2");
_array.push_back("value 3");
}
function_2(){
_array[0] = ("new value 1");
}
private:
std::vector<std::string> _array;
};
int main(){
Foo f;
f.function_1();
f.function_2();
}
Even better, have a std::vector<std::string>, so you can safely modify the contents without having to worry about memory management. Though, to this won't be a single block any more. Now I got to ask, how exactly do you want to pass the buffer to the socket?
You actually have a fatal error in your function_1(). The following code will cause array to point to a character, with the value 3. Then, it will overwrite various parts of neighboring memory, basically causing a buffer overflow.
void function_1() {
array = new char(3);
array[0] = "value 1";
array[1] = "value 2";
array[2] = "value 3";
}
What you probably want to do is create something like:
char **array;
array = new char*[3];
array[0] = new char[strlen(...)];
array[0] = strncpy(array[0], ..., strlen(...)];
// etc
A much safer and cleaner way of accomplishing this would be to do what Xeo is suggesting, and using a std::vector instead of a plain array.
Since array is global, it is visible to other functions. Memory allocated with new[] stays around until it is freed by delete[].
It will exist and be global, because the char * array pointer is global.
The memory that you allocate in function1 will stay allocated after the program exits the scope of the function and will work as expected in functions 2 and 3. Notice however, that behaviour is undefined if you call functions 2 and 3 before function one. In general though, what you're trying to do here looks like bad design, but for the sake of the question I won't bug you about that now :)
It would greatly improve the clarity of your code if you'd:
use a std::vector, especially if you plan to resize it later
use a std::string to represent strings
pass the array or vector by reference to the functions that need it.
int main() {
std::vector<std::string> vect;
function_1(vect);
function_2(vect);
}
where your functions look like:
void function_1(std::vector<std::string> & Vect)
typedefs help manage the argument types
This way you won't have to worry about leaks as the vector will deallocate itself when out of scope.
This question already exists:
Closed 11 years ago.
Possible Duplicate:
c++ warning: address of local variable
char* strdup(const char* s)
{
char dup[strlen(s)];
for (int i = 0; i<strlen(s); i++)
{
dup[i]=s[i];
}
return dup;
}
This function is supposed to hold the new array that has been read backwards plus another slot. When I compile it I get the error "warning: address of local variable 'dup' returned" and when I run the program it returns the memory address.
char dup[strlen(s)] defines a local stack variable; this goes out of scope when the function ends, so any attempt to access it after that will result in undefined behaviour.
Your options are:
Use a heap variable (obtained using new). You will have to remember to delete it at some point.
Have the function write into an existing buffer, provided by the caller (e.g. void strdup(char *out, const char *in)).
Use C++ constructs like std::string, which do all the hard work for you.
As you have marked your question "C++", I strongly recommend Option #3.
Your definition specifies an char array pointer as its return type but you initialize a char array inside your function and try to return it. Try this:
char* strdup(const char* s)
{
char *dup = new char[strlen(s)];
for (int i = 0; i<strlen(s); i++)
{
dup[i]=s[i];
}
return dup;
}
The problem is that you never allocate dup on the heap, so when you exit the stack frame, dup will automatically be removed with the stack frame. This means that it's not possible to have a valid reference to dup, as it ceases to exist once you exit the function.
This should work:
char* strdup(const char* s)
{
char* dup = new char[strlen(s)];
for (int i = 0; i<strlen(s); i++)
{
dup[i]=s[i];
}
return dup;
}
EDIT: when you are done, don't forget to use 'delete' to free the memory ;)
you can't return dup[] because, as it is, it's a local variable and won't be valid outside the function (well, the memory it points to won't be valid anymore). You have to call something like malloc(), which allocates memory on the heap (space visible by all your app)
char* strdup(const char* s)
{
char dup[strlen(s)]; // defines *local* variable on *stack*
for (int i = 0; i<strlen(s); i++)
{
dup[i]=s[i];
}
return dup; // returning dup[0] = dup address
}
You are returning address of local variable, created on stack. When you return from the function the stack will be rewind and your dup variable gone.
The line
char dup[strlen(s)];
will not work in C++. Arrays need a constant size specified at compile time; strlen(s) is a variable.
As far as your actual warning is concerned, it is a bad practice to return a pointer to a local variable to the caller; since the local variable (in this case, the array dup) is allocated on the stack, when the function returns, it is deallocated, and hence, the returned pointer may be invalid. Compilers are designed to catch such errors and flag a warning saying that this could be a potential source of problems.
The dup variable is an array of char and is allocated on the stack rather than the heap (via new or malloc). As soon as the stack frame is left (that is: the function is left) this is undefined memory that will be overwritten by other things soon.
You need to turn dup into a char * and use new or malloc to allocate the necessary memory.