I am getting seg fault while trying to delete a pointer(for char array). Please help me. Am i doing anything wrong here. Please find the code snippet and output below.
Code :
# include <iostream>
using namespace std;
int main()
{
int *p = new int;
const char* c = new char[100];
c = " hello";
*p = 10;
cout << "c= " << c << "*p = " << *p << endl;
delete p;
delete c;
c = NULL;
p = NULL;
return 0;
}
output:
c= hello*p = 10
Segmentation fault (core dumped)
Edit :
If i do not use new and delete for a character array, Is it a memory leak? I can not use string in my code, so what is the correct way to use const char* variable?
Thanks in advance.
You allocate memory and assign it to the pointer c here
const char* c = new char[100];
But then you reassign the pointer:
c = " hello";
That means you loose the original pointer, and now c points to the literal string "hello" which you can't delete.
What you should to instead is copy the string into the allocated memory.
You are making c point to a string literal here:
c = " hello";
then you attempt to delete it
delete c;
This is undefined behaviour. And you leak the array c pointer to originally.
Note: if c pointed to the original dynamically allocated array, you would need to delete it by calling delete [], not delete. Also, in C++ you would usually avoid such manual memory allocation:
#include <string>
#include <iostream>
int main()
{
std::string c = "hello";
int p = 10;
std::cout << "c= " << c << ", p = " << p << std::endl;
}
c = " hello";
Makes it point to a static const char buffer(string literal) that you don't have control on. It does not copy the string in the array. When calling delete on this kind of memory, you get the crash.
You will also never be able to free the originally allocated memory.
If you want to do so:
delete [] c;
is what you need.
your code is trying to delete a variable in read only data section, hence getting a segmentation fault.
And the code also contains a memory leak, c = new char[100] causes to allocated 100 bytes, and then the c pointer points to the "hello" literal, hence the address that was received using new is lost, hence a memory leak..
use string copy function to copy the literal "hello" to the allocated memory.
Related
I'm just looking at the following code snippet:
#include<iostream>
#include<cstring>
using namespace std;
class String
{
private:
char *s;
int size;
public:
String(const char *str = NULL); // constructor
~String() { delete [] s; }// destructor
void print() { cout << s << endl; }
void change(const char *); // Function to change
};
String::String(const char *str)
{
size = strlen(str);
s = new char[size+1];
strcpy(s, str);
}
void String::change(const char *str)
{
delete [] s;
size = strlen(str);
s = s + 1;
s = new char[size+1];
strcpy(s, str);
}
int main()
{
String str1("StackOverFlow");
String str2 = str1;
str1.print();
str2.print();
str2.change("StackOverFlowChanged");
str1.print();
str2.print();
return 0;
}
I expect the output as:
StackOverflow,
StackOverflow,
StackOverflow,
StackOverflowChanged.
Before str2.change("StackOverFlowChanged") line, both str1 and str2's s point to the same memory location. However, in change method, since the pointer value changed, I except now str1 and str2's s point to the different locations and this is not the case. Can somebody explain why this is the case?
After calling str2.change, str1 no longer has a valid pointer. Since the two objects were sharing the same pointer, by deleting the array in one object, the other object now points to a deleted array. Attempting to access the array pointed to by str1 is undefined behavior, so str1.print() is invalid code.
Now, in this particular case, odds are good that the new char[] in str2.change just so happens to return a pointer to an address identical to the one that was just deleted. After all, the memory was just freed up, and no other allocations were made in the meantime. So while str1's pointer is still invalid, it just so happens to work out to pointing at a valid string by the time str1.print gets called.
But that's just happenstance; an implementation didn't have to do that. Undefined behavior is undefined, and you need to properly follow the Rule of 5. Or just use std::string.
The problem is that you called delete[] on the memory pointed by str1.
The runtime library is then allowed to reuse the same memory for the next allocation call and apparently this is what happened.
str1 didn't change the memory it pointed to, but the content changed.
Note that using a pointer to memory after it has been delete[]d is undefined behavior. So indeed anything can happen.
When you write classes that own heap allocated memory a lot of care should be taken about who owns the memory and when this memory is going to be released; in particular a lot of attention should go to copy constructor and assignment operator because the automatically generated code is rarely the correct one in case of memory owned using raw pointers.
No, str1 and str2 do not point to the same memory location, before str2.change("StackOverFlowChanged") line. str2 is in a different location but with the same value as of str1. You can verify this using -
cout << &str1 << '\t' << &str2 << endl;
It will show that they have different locations in memory.
I'm doing some learning exercises in c++ and I ran into an interesting question. Take this sample program.
#include <string>
#include <iostream>
char* pointer1;
void temp() {
char* s1 = new char;
*s1 = 'z';
pointer1 = s1;
std::cout << *pointer1 << std::endl;
for (int i = 0; i < 90000; i++) {
// Waste some processor time.
}
}
int main() {
temp();
std::cout << *pointer1 << std::endl;
delete pointer1;
//delete &pointer1;
std::cout << *pointer1 << std::endl;
return 0;
}
When you run it it prints out 'z' twice then some random garbage. Which is what I expected. If you un-comment 'delete &pointer1' and comment out the first delete and run the program you get an invalid pointer error from the output. I'm assuming this is deleting the address and what's actually stored there is remaining.
My question is when calling 'delete pointer1' does it delete 'char* s1' or just the address to where ever the s1 is stored? When calling 'delete &pointer1' is the address being deleted but s1 still in memory?
The address that pointer1 points to has been allocated by new. Hence, it is correct, even necessary, to call delete on that address.
However, &pointer1 gives you the address where pointer1 itself is stored. And this memory block has not been allocated by new. Hence, it is strictly illegal to call delete on it, which is precisely what the error is telling you.
So, yes, delete pointer1 frees the memory that has been allocated by new previously. But no, delete &pointer1 doesn't do anything but being illegal.
Additionally, accessing memory you called delete on previously is undefined behavior. So, your second *pointer1 is also nothing you want to write in a program that you do not want to crash or, even worse, that gives you unpredictable results.
int *ab = (int *)5656;
cout << *ab; //Here appcrash.
int *ab;
*ab = 5656;
cout << *ab; //These block crashes the app too.
But i can get the hex value of content of pointer if i write this:
int *ab = (int *)5656;
cout << ab; //Output is hex value of 5656.
So i want to ask: * is a operator that brings the contents of pointer(?) but why in this(these) example(s) app crashes?
And i can use that operator if i change code into this:
int a = 5656;
int *aptr = &a;
cout << *aptr; //No crash.
And why dereference operator(*) brings the only first character of a char:
char *cptr = "this is a test";
cout << *cptr; // Here output = 't'
cout << cptr; // Here output = 'this is a test'
int *ab = (int *)5656;
cout << *ab; //Here appcrash.
In this case, you are setting the pointer ab to point at the address 5656. Do you know what's at this address? No you don't. You are telling the compiler to trust you that there is an int there. Then, when you dereference the pointer with *ab, you obviously find that there isn't an int there and you get undefined behaviour. In this case, your program crashes.
int *ab;
*ab = 5656;
cout << *ab;
In this case, you have an uninitialised pointer ab which you then dereference to assign 5656 to the int it points at. Since it's uninitialised, dereferencing it gives you undefined behaviour. Think of it this way. You haven't put an addres in ab so you don't know where it points. You can't just dereference it and hope it points at an int.
int a = 5656;
int *aptr = &a;
cout << *aptr;
This is fine because you know you have an int object with value 5656 and you know that aptr contains the address of that int object. It's perfectly fine to dereference aptr.
const char *cptr = "this is a test";
cout << *cptr; // Here output = 't'
cout << cptr;
(Your code was using a deprecated conversion to char*, so I changed it to a const char*.)
The string literal "this is a test" gives you an array containing const chars. However, it then undergoes array-to-pointer conversion giving you a pointer to its first element. Since each element is a const char, the pointer you get is a const char*. You then store this pointer in cptr.
So cptr points at the first element of the string. Dereferencing that pointer gives you that first element, which is just the first character of the string. So you output t.
The I/O library has special overloads that take const char*s and treat it as pointing to a string of characters. If it didn't, cout << cptr would just print out the address in cptr. Instead, these special overloads will print out the null-terminated array of characters that cptr is assumed to point to.
I think it's worth noting that the application crashes you are observing are due to the fact that it is very unlikely that your process (i.e. program) owns the memory at the location you specify: 5656.
Modern operating systems disallow access to memory allocated by other processes.
Imagine what a headache it would be if that we're not the case: one program could modify the data associated with another one!
The "access violation" message is a helpful hint that you're accessing memory that your process does not own.
is a operator that brings the contents of pointer(?)
No. * is a operator that brings the contents of memory which pointer point to.
Here:
int *ab = (int *)5656;
cout << *ab; //Here appcrash.
Pointer ab contains 5656. *ab tries to access memory which pointer ab point to => *ab tries to access memory at address 5656. Your program is not allowed to access memory at address 5656 because it is not allocated or read-only => app crashes.
And i can use that operator if i change code into this:
int a = 5656; int *aptr = &a; cout << *aptr; //No crash.
Here you allocate and initialize memory: int a = 5656;
Here you write address of previously allocated memory to pointer: int *aptr = &a;
Here you access memory which was previously allocated: *aptr (memory contains 5656).
You have right to access it => app doesn't crash.
And why dereference operator(*) brings the only first character of a char
Because char is not string, char is character. When you dereference pointer to char, you get char.
C has no built-in type for string. That's why it's common to use pointer to memory containing string. This pointer usually points to a first character of string: char * - pointer to character
This code causes a Segmentation Fault:
int main(){
char *p;
char a[50] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
p = (char *)malloc(50*sizeof(char));
if(!p){
cout << "Allocation Failure";
cout << "\n";
}
else{
cout << "Allocation Success";
cout << "\n";
p = a;
cout << p;
cout << "\n";
free(p);
}
return 0;
}
The output after executing this program is:
Allocation Success
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Segmentation fault
I am not able to find the bug. What may be reason?
This:
p = a;
copies the pointer, not the contents of the pointed-to memory. p now points at the first element of the array a. So when you do free(p), you're trying to free a non-dynamic array, which doesn't make any sense.1
You should investigate strncpy() to copy strings.
1. And it also causes a memory leak.
You're calling free on a block of memory that wasn't allocated using one of the malloc methods.
When you do: p = a you're assigning to p the memory used by the stack array a. That memory wasn't allocated using malloc and hence it can't be freed using free.
Furthermore with that re-assignment, you'll lose track of the block that you originally allocated with malloc and assigned to p, causing a memory leak.
char a[50] allocates an array of fifty characters on the stack. a therefore points at an address on the stack.
p = a sets p to point at the same address as a. Therefore after p = a, p points at an address on the stack. Remember, p contains an address.
Afterwards, free(p) tries to free a region of memory on the stack, which is illegal. You can only free memory you got from malloc().
you actually meant memcpy(p,a,50); not p=a, remember C does not have a string data type.
p = a; // p points a
Executing this line, p should be pointing to const string (char *).
You cannot free() anything that is not obtained by calling malloc or calloc. Since in this example you try to free() a const string, you get an error.
#include<stdio.h>
#include<string.h>
#include<iostream.h>
using namespace std;
int main()
{
const char *a="hello";
char *b;
strcpy(b,a);
cout<<b;
return 0;
}
This code theows memory exception . why ?
char* b is a pointer that is yet to be pointed at any memory... it simply holds a random address. You attempt to copy the content of a over the memory at that address. Instead, first point b at some memory - either a local array or from new char[].
char buffer[128];
char* b = buffer;
char* b = new char[128];
// use b for a while...
delete[] b; // release memory when you've finished with it...
// don't read/write data through b afterwards!
( or simply copy it directly into buffer :-) )
BTW, C++ has a <string> header that's much, much easier to use:
#include <string>
int main()
{
std::string s = "hello";
std::string t = s;
std::cout << t << '\n'; // '\n' is a "newline"
}
If you're writing new code, prefer std::string, but sooner or later you'll need to know about all that char* stuff too, especially when C++ code needs to interact with C libraries.
Exception is due to uninitialized,
char *b;
Either allocate b on stack as an array,
char b[SIZE];
Or allocate using new and later delete it. But the best way is,
std::string b;
b = a;
Here
char *b;
strcpy(b,a);
b is not initialized - using its value is undefined behavior. Even if using its value is okay on your platform it holds "whatever" address - copying a string onto "whatever address" is undefined behavior.
You have to allocate a memory block by any legal means and set b to start of that block. The block must be large enough to hold the string together with terminating null character.
b is uninitialised. It is a pointer, but it doesn't point anywhere (it holds NULL or a garbage value). strcpy tries to write to it, but it must have a pointer to write to. You must assign some chunk of memory to b before you can use it. Eg:
char *b = new char[20]; //dynamically allocate some memory
or
char b[20]; //allocate some memory on the stack
A few things are "wrong" with your code.
Use:
#include <iostream>
You're not using C++ strings.
std::string a = "hello";
std::string b = a;
If you insist on using strcpy(), please allocate some memory for b:
b = new char[strlen(a)];
// Your code here
delete[] b;
There's lots of memory to go around. No need to go about corrupting stuff.
You need to allocate memory (e.g. using malloc) for the destination before you can copy something there.
The char pointer b is initiaized to 0 when the program runs. So you can't copy anything to it.
If you want to copy a string, in C++ style, do this instead:
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a = "hello";
string b = a;
cout << b << endl;
return 0;
}
strcpy(dest, source)
In your code b is your dest and it is not initialized. Even if you switch them around it will still crash because you have not allocated memory for b. The destination memory has to be pre-allocated.