Q: Different output depending delete I have this code:
#include <iostream>
using namespace std;
char* pass(char* p){
    char* a = new char[10];
    a[0] = 'S';
    a[1] = 'e';
    a[2] = 'r';
    a[3] = 'g';
    a[3] = 'e';
    a[3] = 'y';
    a[4] = '\0';
    p = a;
    //delete [] a;
    return p;
}
int main(int argc,char* argv[]){
    char* p1 = new char[1000];
    p1[0] = 'G';
    p1[1] = 'e';
    p1[2] = 'r';
    p1[3] = 'y';
    p1[4] = '\0';
    char* p2 = p1;
    cout << p2 << endl;
    cout << pass(p2) << endl;
    delete [] p1;
}

and the output is :
Gery
Sery

but if I uncomment the line delete [] a
I got this output :
Gery
ê§É

Why?

A: In this function
char* pass(char* p){
    char* a = new char[10];
    a[0] = 'S';
    a[1] = 'e';
    a[2] = 'r';
    a[3] = 'g';
    a[3] = 'e';
    a[3] = 'y';
    a[4] = '\0';
    p = a;
    //delete [] a;
    return p;
}

the parameter is a local variable of the function. After exiting the function it is destroyed.
You can imagine the function and its call the following way
pass(p2);

char* pass(/*char* p*/){
    char* p = p2;
    char* a = new char[10];
    a[0] = 'S';
    a[1] = 'e';
    a[2] = 'r';
    a[3] = 'g';
    a[3] = 'e';
    a[3] = 'y';
    a[4] = '\0';
    p = a;
    //delete [] a;
    return p;
}

As you see the original pointer p2 will not be changed in the function. The function changes its local variable p that is declared as a parameter.
If to uncomment the delete statement then the memory pointed to by the return value will be deleted and the returned pointer will be invalid. In this case the program has undefined behaviour due to statement
cout << pass(p2) << endl;

where there is an attempt to access the deleted memory using the return value of the function.
So there is no sense to return pointer to deleted memory.
What you want to do can be achieved in three ways
The first one is to declare the parameter as reference
char* pass(char* &p){
           ^^^^^^^^
    char* a = new char[10];
    a[0] = 'S';
    a[1] = 'e';
    a[2] = 'r';
    a[3] = 'g';
    a[3] = 'e';
    a[3] = 'y';
    a[4] = '\0';
    p = a;
    return p;
}

and call the function like
cout << pass(p2) << endl;

The second one is to declare the parameter as pointer to pointer that is to accept the original pointer indirectly
char* pass(char* *p){
           ^^^^^^^^
    char* a = new char[10];
    a[0] = 'S';
    a[1] = 'e';
    a[2] = 'r';
    a[3] = 'g';
    a[3] = 'e';
    a[3] = 'y';
    a[4] = '\0';
    *p = a;
    ^^^^^^^^
    return *p;
    ^^^^^^^^^^
}

and call the function like
cout << pass(&p2) << endl;

And at last you could simply assign the returned value to the original pointer. For example
char* pass(char* p){
    char* a = new char[10];
    a[0] = 'S';
    a[1] = 'e';
    a[2] = 'r';
    a[3] = 'g';
    a[3] = 'e';
    a[3] = 'y';
    a[4] = '\0';
    p = a;
    return p;
}

and call the functionj like
cout << ( p2 = pass(p2) ) << endl;

though in this case the parameter is obsolete.
In any case you should delete the allocated memory at the end of the program like
delete [] p2;


A: p = a

does not copy the values.
What you are looking for is probably:
memcpy(p, a, 10*sizeof(char));


A: Because your uncommented line releases the memory you returned, and your compiler, probably as a debug aid, overwrote the released memory.
Your p is passed by value, so p = a; does not, in fact, change p1 inside main. You essentially initialize memory, delete it, and then return a pointer to the deleted memory.
Without the extra delete, you just leak that memory.
