global variables not retaining their values in i2c ISR

hello ,
I am trying to make communication between two arduinos using i2c; i2c communication is working fine when i am using static data like this to send from ISR of slave to master

void requestCallback()
{
  for(x=0;x<4;x++)
  buffer[x]=x;
  Wire.write(buffer, 4);
}

but whats happening with buffer when i am dynamically updating it with variables in i2c isr i am not understanding it....
here is my code for slave

#include <Wire.h>
const byte SlaveDeviceId = 1;
char *p;
int length=0;
int8_t ans=0,l;
int8_t sendATcommand(char* ATcommand, char* expected_answer1, unsigned int timeout);
char response[100];
int t=0;
uint8_t buffer[4];
int cell_id_2G[5];

void setup()
{
  // Start I²C bus as a slave
  Wire.begin(SlaveDeviceId);
  // Set the callback to call when data is requested.
  Wire.onRequest(requestCallback);
  Serial.begin(9600); 
  Serial2.begin(9600);
}


void loop()
{
  ans=sendATcommand("AT", "OK", 2000);
  ans=sendATcommand("AT+QNWCFG=\"NWSCANMODE\",0", "OK",2000);
   Serial.println("ENTER 2G");
       sendATcommand("AT+CREG=2", "OK", 2000);
       ans=sendATcommand("AT+CREG?", "+CREG:", 2000);
       if(p!=NULL)
       {
         
           for(l=0;l<4;l++)
            {
              cell_id_2G[l]=p[12+l];
            }
              cell_id_2G[l]='\0';
       }
            else
           {
              cell_id_2G[0]='\0'; 
           }
           
           Serial.print(cell_id_2G[0]);
           Serial.print(cell_id_2G[1]);
           Serial.print(cell_id_2G[2]);
           Serial.println(cell_id_2G[3]); 
}



void requestCallback()
{

  Serial.print("In ISR");
  for(l=0;l<4;l++)
  {
  buffer[l]=cell_id_2G[l];
  Serial.print(buffer[l]);
  Serial.print(cell_id_2G[l]);
  }
  Wire.write(buffer,23);
}
----------------------------******************-------------------------(this section of code is working perfectly fine)
int8_t sendATcommand(char* ATcommand, char* expected_answer1, unsigned int timeout){

    uint8_t x=0,  answer=0;
   
    unsigned long previous;

    memset(response, '\0', 200);    // Initialize the string

    delay(100);

    Serial2.println(ATcommand);    // Send the AT command 


        x = 0;
    previous = millis();

    // this loop waits for the answer
    do{
        if(Serial2.available() != 0){    
            response[x] = Serial2.read();
            x++;
           //Serial.println(response);
            // check if the desired answer is in the response of the module
           
        }
        // Waits for the asnwer with time out
    }
    while(((millis() - previous) < timeout));    
     if ((p=strstr(response, expected_answer1)) != NULL)    
            {
                answer = 1;
            }
    return answer;
}

and here is my hyper terminal output

In ISR00000000In ISR00000000In ISR00000000In ISR00000000ENTER 2G
In ISR00000000In ISR00000000In ISR00000000In ISR0000000065485168
In ISR00000000In ISR00000000In ISR00000000In ISR00000000ENTER 2G
In ISR00000000In ISR00000000In ISR00000000In ISR0000000065485168
In ISR00000000In ISR00000000In ISR00000000In ISR00000000ENTER 2G
In ISR00000000In ISR00000000In ISR00000000In ISR0000000065485168

in ISR the value of cell_id_2G is printed as 0000,so at master also it is printing 0000...but in the main loop it is 65,48,51,68
y this variable is losing its value....someone plz help me with this....

thanks
asma

Well here's an obvious show-stopper:

  Serial.print("In ISR");

Can't do that - there are many things that won't work in an ISR
because they rely on interrupts themselves, and Serial is one.
Also delay, millis...

You have variables accessed in the ISR that are not declared volatile, so
they need to be made volatile.

You also update cell_id_2G in loop without first disabling interrupts,
so that your ISR can see that array in a garbled state should an
interrupt happen during that for loop.

Rules for ISRs:

keep them short

don't call functions that themselves wait for interrupts

all variables shared between ISR and rest of program need to be volatile

disable interrupts when updating or reading shared state to avoid garbling
it. The exception to this is when the state is a single byte or char, since access
to a byte is already "atomic".

I tried using volatile keyword ,i tried disabling interrupt....but still its not working...

I'm sorry to say, but there are too many problems with your code.
These are only a few:
You can not use the Serial library from an I2C interrupt routine.
You write 23 bytes of 'buffer', while that array is only 4 bytes.
You set 200 bytes of 'response' to zero, but that variable is only 100 bytes.
You test variable 'p' against 'NULL', but 'p' is not set to a value at that moment. In the following code you use 'p[..]' as if it was an array, but I'm not sure if 'p' is assigned to a location at that point.

Verify your names of variables and your "for loop" initialization.
Using single letter variables can be source of bugs - e.a. lower case of letter "L" and numeral one "1".
Aslo is seems that some of the return values do not have a real source.
Use Serial, optionally activated by #define DEBUG, to verify your code flow and actuall values , you are flying pretty blindfolded.
You can always remove / undefine the DEBUG when your code works as desired.

Thank you so much everyone....It really helped me a lot...
Problem was memset as told by Caltoa....when i changed it to 100....
now its working properly....
i am checking pointer p for NULL cause strstr function returns NULL if it do not find the requested string in strstr....

i know i have lots of bug in my program ....as i am new to programming....please help me to optimize my code....
what else i have to do change....i have done the changes as told by Caltoa and Vaclav....
i didnt understand about #define DEBUG....
any suggestions would be really helpful

thanks
asma

Programmers often use preprocessor directives, like #define to toggle code into and out of a program. For example:

#define DEBUG    1    // You don't really need a value, but I usually use one
//...many lines of code...

#ifdef DEBUG
myVal = 50;
#endif
//...more lines of code

In this example, you surround the variable you're interested in with the #ifdef directive. If you have defined DEBUG earlier in the program, the test value for myVal is compiled into the program. You can put as many lines of code between the #ifdef and #endif as you want. When you're done debugging, just place a comment before the #define (e.g., //#define DEBUG 1). When you recompile the program, the myVal statement is no longer compiled into the program. Sometimes you'll hear this called "scaffolding code".

Thank you econjack for explaining me....this is new to me...
I will try it....

thanks asma