Swair
Swair

Reputation: 1513

what is this weird behavior in this c code?

I don't have clear idea how the following two pieces of code show different behavior:

code:

#include <stdio.h>

void set(char** addr) {
  char* str = "testa";
  *addr = str;
}

void _set(char*** addr) {
  char* arr[] = {"testb"};
  *addr = arr;
}

int main() {
  char* a;
  set(&a);
  printf("'%s'\n", a);
  printf("'%s'\n", a);

  char** b;
  _set(&b);
  printf("'%s'\n",b[0]);
  printf("'%s'\n",b[0]);
}

Output:

testa
testa
testb
testb

When I remove the first bit, the testa part, the code is:

void _set(char*** addr) {
  char* arr[] = {"testb"};
  *addr = arr;
}

int main() {
  char** b;
  _set(&b);
  printf("'%s'\n",b[0]);
  printf("'%s'\n",b[0]);
}

Output:

'testb'
'UH▒▒AWE1▒AVAUATSH▒▒8▒E▒'

Upvotes: 0

Views: 151

Answers (2)

spinlock
spinlock

Reputation: 108

You are experiencing memory corruption. Your code in main() referring memory on the stack which will likely be corrupted when a new function is called. "testb" itself isn't corrupted, but arr is (the location containing the address to the string literal "testb")

If you make the following change, it will work:

char* arr[] = {"testb"}; /* Make arr global to fix the bug */

void _set(char*** addr) {
   /* alternatively, you could make arr static here, static char* arr... */    

   *addr = arr;
}

With enough digging, it should be explainable why it works in the first case, but not in the second, and it will be deterministic and repeatable. For example, try this:

void _set(char*** addr) {
  char pad[3]; // <-- Insert a 3 byte stack variable
  char* arr[] = {"testb"};
  *addr = arr;
}

You should see something different now (hmmm, does that second line look familiar?):

'testb'
''%s'
'

Upvotes: 1

The seta() function defines str as a pointer to a string. The string itself is an array of characters 't','e','s','t','a','\0' located on the heap.

The _seta() function defines something completely different: an array of (one) pointers to (one) strings. The array itself is located on the stack, meaning that the array will go out of scope (i.e. get thrashed) as soon as the function returns. The string itself is another array of characters 't','e','s','t','b','\0', which is located on the heap, just as above.

Thus: the call _set(&b); obtains a pointer to undefined memory. The fact that everything seemed to work when you called set(&a); beforehand, was just pure bad luck.

Upvotes: 0

Related Questions