My understanding is that in C and C++, creating a character array by calling:
char *s = "hello";
actually creates two objects: a read-only character array that is created in static space, meaning that it lives for the entire duration of the program, and a pointer to that memory. The pointer is a local variable to its scope then dies.
My question is what happens to the array when the pointer dies? If I execute the code above inside a function, does this mean I have a memory leak after I exit the function?
it lives for the entire duration of the program
Exactly, formally it has static storage duration.
what happens to the array when the pointer dies?
Nothing.
If I execute the code above inside a function, does this mean I have a memory leak after I exit the function?
No, because of (1). (The array is only "freed" when the program exits.)
No, there is no leak.
The literal string is stored in the program's data section, which is typically loaded into a read-only memory page. All equivalent string literals will typically point to the same memory location -- it's a singleton, of sorts.
char const *a = "hello";
char const *b = "hello";
printf("%p %p\n", a, b);
This should display identical values for the two pointers, and successive calls to the same function should print the same values too.
(Note that you should declare such variables as char const * -- pointer to constant character -- since the data is shared. Modifying a string literal via a pointer is undefined behavior. At best you will crash your program if the memory page is read-only, and at worst you will change the value of every occurrence of that string literal in the entire program.)
const char* s = "Hello"; is part of the code (program) - hence a constant never altered (unless you have some nasty mechanism altering code at runtime)
My question is what happens to the array when the pointer dies? If I
execute the code above inside a function, does this mean I have a
memory leak after I exit the function?
No there will be no memory leak and nothing happens to the array when the pointer dies.
A memory leak could be possible only with dynamic allocation, via malloc(). When you're malloc() something, you have to free() it later. If you don't, there will be a memory leak.
In your case, it's a "static allocation": the allocation and free of this memory space will be freed automatically and you don't have to handle that.
does this mean I have a memory leak after I exit the function?
No, there is no memory leak, string literals have static duration and will be freed when the program is done. Quote from the C++ draft standard section 2.14.5 String literals subsection 8:
Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration
Section 3.7.1 Static storage duration says:
[...] The storage for these entities shall last for the duration of the program
Note in C++, this line:
char *s = "hello";
uses a deprecated conversion see C++ warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] for more details.
The correct way would be as follows:
const char *s = "hello";
you only have to free if you use malloc or new
EDIT:
char* string = "a string"; memory allocation is static, and not good practice (if it will be constant the declaration should be a const char*)
because this is in the stack when the function ends it should be destroyed along with the rest of the local variables and arguments.
you need to use specific malloc/free and new/delete when you allocate the memory for your variable like:
char *string = new char[64]; --> delete string;
char *string = malloc(sizeof(char) * 64); --> free(string); //this is not best practice unless you have to use C
Related
This question already has answers here:
C++ management of strings allocated by a literal
(4 answers)
Closed 8 years ago.
I have tough problems while trying to de-allocate this pointer.
I'm having this error:
error for object 0x10007fd20: pointer being freed was not allocated
I have the following structure:
char * doSomething() //I cannot change this method.
{
return "hello world";
};
int main ()
{
char * var= doSomething();
cout<< var<<endl;
delete[] var;
};
Please consider that I cannot use string, because I'm not being provided with the doSomething method. As I'm using it a lot.. after a while the app collapses because of the RAM memory use.
You are trying to delete[] a static string. You only want to delete[] objects you have created with new[].
You can delete only what was allocated using the corresponding operator new. String literals have static storage duration. They are not dynamically allocated. According to the C++ Standard
8 Ordinary string literals and UTF-8 string literals are also referred
to as narrow string literals. A narrow string literal has type “array
of n const char”, where n is the size of the string as defined below,
and has static storage duration (3.7).
I see multiple potential issues:
you are using delete[] on a string literal, wrong, and that's why you are getting the error
you are converting a string literal to a char*, which is deprecated and insecure (since you can't modify a string literal)
you are returning a pointer to a local variable, in your situation this is allowed because you are working with string literals but in general
int *function() { int x = 10; return &x; }
Should never be done, if you return a pointer to something in a function, be sure it is dynamically allocated or statically allocated but not allocated on stack.
In my belief, string literals like "Hello world" is stored in the static section of your program instead of on the stack. That means, there is only one copy of "Hello world" in the memory, no matter how many times you call the function. And those calls should return just the same address. The RAM problem of your program is not caused by this issue.
struct st{
int a;
char *ptr;
}obj;
main()
{
obj.a=10;
obj.ptr="Hello World"; // (1) memory allocation?
printf("%d,%s",obj.a,obj.ptr);
}
ptr is declared in struct. When the assignment of Hello world occurs, memory is not allotted and yet this program works fine and gives output properly. Shouldn't it fail/crash when assignment done at marker (1)?
"Hello World" is a string literal residing in a read-only memory section (.rodata) of your program. You point to this section then print the contents. The program behavior is 100% well-defined and should not crash.
It is however good practice to always declare pointers to string literals as const char*, because you are not allowed to modify string literals.
It is perfectly valid.
At compile time (minus compiler optimizations), they are placed in the text/rodata segment of the code. Not sure if you are familiar with the layout of an executable in memory (also known as the runtime environment), but you have the Text, Data, BSS, Heap and Stack.
like
obj.ptr="Hello World";
will place Hello World in the read-only parts of the memory and making obj.ptr a pointer to that, making any writing operation on this memory illegal.
It has no name and has static storage duration (meaning that it lives for the entire life of the program); and a variable of type pointer-to-char, called obj.ptr, which is initialised with the location of the first character in that unnamed, read-only array.
At runtime, the char pointer is allocated on the stack and is first set to point to the area in memory where the string Hello World is.
First, the answer differs somewhat depending on the language (C
or C++), and in the case of C++, the version of the standard.
In both cases, however, "Hello World" is a string literal: in
C, it has typechar [12], and in C++, typechar const [12]`,
and the array has static lifetime, so exists for the lifetime of
the program.
In C, when you assign it to a char*, you have the standard
array to pointer conversion; in C++ pre-C++11, you have
a deprecated char const[] to char* conversion, which is only
valid if the char const[] is a string literal—the
compiler should warn; in C++11, the conversion is illegal, and
your program shouldn't compile (but I'm willing to bet that it
will for many years hence).
my compiler (g++ 4.7.2) throws a warning:
warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
If you don't get this warning, you can try to pass -Wall to your compiler (imo always a good idea)
When you're assigning a string literal to a char pointer you're not assigned memory !
All it does is searching a part of the memory for the string, if it is found - it points to the start of it - if it is not found it creates it. Either way - no memory is assigned and the pointer turns into a constant (read-only) - just try and see you can't change it as it is a constant in memory - Sometimes it's good if you don't want to change that string and sometimes it's not - depends on what you want to do :)
for the following code I was wondering if there is just an array created in the stack or if there is also an array created in the static. I'm just kind of confused with array creation from a string.
char str[] = "White";
I'm assuming this creates a pointer in the stack called str which points to an array with the following contents, "White\0", in the static memory. Is this correct as an assumption?
Nope.
"White" is an array of char[6] in static memory somewhere. (or magic land, it's not specified, and is completely irrelevant). Note that it may or may not be the same static array as another "White" elsewhere in the code.
char str[] = "White"; creates a new local char[6] array on the stack, named str, and copies the characters from the static array to the local array. There are no pointers involved whatsoever.
Note that this is just about the only case where an array can be copied. In most situations, arrays will not copy like this.
If you want a pointer to the magic static array, simply use const char* str = "White";
Phonetagger notes that if the line of code is not in a function, then str is not on the stack, but also in the magic static memory, but the copy still (theoretically at least) happens just before execution begins of code in that translation unit.
Wrong. What you described is what happens when you write:
const char * str = "White";
Instead,
char str[] = "White";
creates an array on the stack (large enough to hold that string), and initializes it with that text. "Regular" string literals and the initialization syntax for char arrays are unrelated stuff.
(as for the implementation, often the compiler emits code that looks like
char str[SIZE_OF_THE_STRING];
strcpy(str, "White");
but that's an implementation-specific detail)
Suppose that I have an array(local to a function) and a pointer
char a[]="aesdf" and char *b="asdf"
My question is whether in the former case the string literal "aesdf" is stored in read only section and then copied on to the local array or is it similar to
char a[]={'a','e','s','d','f','\0'}; ?
I think that in this case the characters are directly created on the stack but in the earlier case (char a[]="aesdf") the characters are copied from the read only section to the local array.
Will `"aesdf" exist for the entire life of the executable?
From the abstract and formal point of view, each string literal is an independent nameless object with static storage duration. This means, that the initialization char a[] = "aesdf" formally creates literal object "aesdf" and then uses it to initialize the independent array a, i.e. it is not equivalent to char *a = "aesdf", where a pointer is made to point to the string literal directly.
However, since string literals are nameless objects, in the char a[] = "aesdf" variant there's no way to access the independent "aesdf" object before or after the initialization. This means that there's no way for you to "detect" whether this object actually existed. The existence (or non-existence) of that object cannot affect the observable behavior of the program. For this reason, the implementation has all the freedom to eliminate the independent "aesdf" object and initialize the a array in any other way that leads to the expected correct result, i.e. as char a[] = { 'a', 'e', 's', 'd', 'f', '\0' } or as char a[] = { 'a', 'e', "sdf" } or as something else.
First:
char a[]="aesdf";
Assuming this is an automatic local variable, it will allocate 6 bytes on the stack and initialize them with the given characters. How it does this (whether by memcpy from a string literal or loading a byte at a time with inline store instructions, or some other way) is completely implementation-defined. Note that initialization must happen every time the variable comes into scope, so if it's not going to change, this is a very wasteful construct to use.
If this is a static/global variable, it will produce a 6-byte char array with a unique address/storage whose initial contents are the given characters, and which is writable.
Next:
char *b="asdf";
This initializes the pointer b to point to a string literal "asdf", which might or might not share storage with other string literals, and which produces undefined behavior if you write to it.
Both a[] ="aesdf" and char a[]={'a','e','s','d','f','\0'} will be stored in function's run time stack and memory will be released when function returns. but for char* b= "asdf" asdf is stored in readonly section and is referred from there.
char a[] = "aesdf";
char a[] = {'a','e','s','d','f','\0'};
These two lines of code have the same effect. A compiler may choose to implement them the same way, or it may choose to implement them differently.
From the standpoint of a programmer writing code in C, it shouldn't really matter. You can use either and be sure that you will end up with a six element array of char initialized to the specified contents.
Will "aesdf" exist for the entire life of the executable?
Semantically, yes. String literals are char arrays that have static storage duration. An object that has static storage duration has a lifetime of the execution of the program: it is initialized before the program starts, and exists until the program terminates.
However, this doesn't matter at all in your program. That string literal is used to initialize array a. Since you do not obtain a pointer to the string literal itself, it doesn't matter what its actual lifetime of that string literal is or how it is actually stored. The compiler may do whatever it sees fit to do, so long as the array a is correctly initialized.
So, I'm wanting to get a better grasp on how string literals in C++ work. I'm mostly concerned with situations where you're assigning the address of a string literal to a pointer, and passing it around. For example:
char* advice = "Don't stick your hands in the toaster.";
Now lets say I just pass this string around by copying pointers for the duration of the program. Sure, it's probably not a good idea, but I'm curious what would actually be going on behind the scenes.
For another example, let's say we make a function that returns a string literal:
char* foo()
{
// function does does stuff
return "Yikes!"; // somebody's feeble attempt at an error message
}
Now lets say this function is called very often, and the string literal is only used about half the time it's called:
// situation #1: it's just randomly called without heed to the return value
foo();
// situation #2: the returned string is kept and used for who knows how long
char* retVal = foo();
In the first situation, what's actually happening? Is the string just created but not used, and never deallocated?
In the second situation, is the string going to be maintained as long as the user finds need for it? What happens when it isn't needed anymore... will that memory be freed up then (assuming nothing points to that space anymore)?
Don't get me wrong, I'm not planning on using string literals like this. I'm planning on using a container to keep my strings in check (probably std::string). I'm mostly just wanting to know if these situations could cause problems either for memory management or corrupted data.
String-literals have the type const char[N] (where N is the length + 1) and are statically allocated. You need not worry about memory issues; if a string is used in your program it is all handled for you, and resides somewhere in program memory (usually read-only).
That is, these are "the same":
static const char str[] = "a string";
"a string"
When you point to a string literal, you are pointing to the first character at the array. In fact, because the type is const char[], it's only safe to point to it via const char*. The conversion from string literal to char* is deprecated, and unsafe.
// the "same"
static const char str[] = "a string";
const char* strPtr = str; // decays
const char* s1 = "a string";
char* s2 = "a string"; // allowed, implicit const_cast
*s1 = 'A'; // not allowed, it's const
*s2 = 'B'; // allowed, it's not const (but leads to undefined behavior)
Firstly, declare the return value of foo as const, because string literals are constants that can't be changed without causing the dreaded "undefined behaviour". This will then force any pointers which use the return value of foo to also be declared as const, and potentially limiting the damage which can be (usually unintentionally) done. String literals are stored in the 'text' area of a binary executable - they're not created as such at run time.