2

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.

2
  • There are several problems with the code you posted: array = new char(3) should be array = new char[3] (square brackets!). You cannot meaningfully assign a char* such as "value1" to array[0], because its type is char and not char*. There's no chance it's going to do what you expect as it stands. Commented Jun 18, 2011 at 23:27
  • 1
    What you're doing is considered very bad practice. Take a look at @Xeo 's answer for a more idiomatic way to approach this. Commented Jun 18, 2011 at 23:30

6 Answers 6

7

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?

Sign up to request clarification or add additional context in comments.

7 Comments

it's a great idea. But I was to use this array as a buffer for socket. So socket can write the received data in it. I am not sure, if socket can use vector for it. I have never seen it before.
@4eloveg: Sure it can, a vector is essentially a safe wrapper around a dynamic array. Just make it std::vector<char*> _array;, allocate enough space (_array.reserve(SIZE);) and pass the socket a &_array[0], which will give them a char**.
@4eloveg: See my edit and the question at the end, how do you want to pass the buffer?
@Xeo: This is indeed the safest and cleanest solution. You get all the benefits of being able to dynamically add and remove data, and you are more or less guaranteed that the buffer will be contiguous.
@4eloveg: So it should be one big, contiguous buffer. Better have a std::vector<char> (note, no pointer) then and make that big enough. :)
|
3

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.

5 Comments

Note that the /* stuff here */ must now become a str(n)cpy and the ... will become a strlen.
@Xeo: Added to the example. But again, I'd strongly caution the OP from doing this as it's much messier than using a vector as in your answer. Even better would be to use the built in std::string class.
Good point about the std::string. But in OP's comment on my answer, he hints that he wants to pass the buffer to a socket, so if he needs a contiguous buffer, that won't work (neither will the char** array though).
@Xeo: Ah, my mistake. I missed that in the question.
Note, I meant "answer" in my last comment. It isn't explicitly said in the question.
2

Since array is global, it is visible to other functions. Memory allocated with new[] stays around until it is freed by delete[].

Comments

2

It will exist and be global, because the char * array pointer is global.

1 Comment

Your are welcome. In another note, that type of programming is bad. For example, if you call function_1 again, nothing will fail but.. the pointer allocated in the 1st call will simply be "forgotten" and therefore unable to be delete[]d. That is called a memory leak.
2

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 :)

1 Comment

hahaha. if you know another solution. I would be glad to hear it. :-) I use char array for received data from socket. Size of data is not predefined. It will be always given at the biggining of every data package. That's why I want to allocate array depends of package size to get all data from socket. :-)
2

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.