0

I'm having some issue with my stack implementation, my push function manipulate the value i send into the function and changes it. I have tried diffrent ways of constructing this but they either don't work or give me corrupted output.

The base idea is the one below here, note: my pop function only walks down one position and doesn't free the memory at the specific position. I can not use strcpy since im working with threads.

Does strdup change the value that it copies, i cant find any information saying that is the case, my understanding is that you are suppose to be able to use the value after it has ben duped.

And how is the correct way to use strdup on a already allocated memory space, i assume that i can't just free it and then use it again.

void stack_push(Stack *s, char *value)
{
   if (s->size == s->capacity) {
       realloc_stack(s);
   }

   if(s->data[s->size] == NULL){
       // The current position does not contain any data.
       s->data[s->size] = strdup(value);

   }
   else{
       free(s->data[s->size]);
       s->data[s->size] = strndup(value, strlen(value) + 1);
   }

   s->size += 1;

}

Edit s->data = char **data

forsb
  • 123
  • 9
  • @user3121023 Thank you for the answer. Do you know anything about what it does with the value it dupes? – forsb Nov 09 '20 at 13:09
  • 1
    You say you are working in a multithreaded environment; since you change state non-atomically in this function, it must be protected by a mutex or such, independent of any library functions you may or may not call (and most of them *are* reentrant). *Do* you protect it? – Peter - Reinstate Monica Nov 09 '20 at 13:29
  • 1
    It just duplicates it. That's it, nothing more. Why would it do anything else? If you want to use or free the source again later, keep your own pointer to it; `strdup()` won't reuse the same address, as that wouldn't be _duplication_... – underscore_d Nov 09 '20 at 13:29
  • 2
    1) No reason for `strndup(value, strlen(value) + 1);`, `strdup(value);` is fine. 2) I suspect your problem is in unposted `realloc_stack();` – chux - Reinstate Monica Nov 09 '20 at 13:32
  • 1
    "Does strdup change the value that it copies" --> No. Best to post a [mcve]. – chux - Reinstate Monica Nov 09 '20 at 13:35
  • Note: The `s->data[s->size] == NULL` is not needed. Entire `if ...else ...` can be replaced with `free(s->data[s->size]); s->data[s->size] = strdup(value);`. `free(NULL)` is OK. – chux - Reinstate Monica Nov 09 '20 at 13:38
  • @Peter-ReinstateMonica Ok, do you mind explaining more what you mean. I do need some sort indexing of my strings – forsb Nov 09 '20 at 13:40
  • @forsb Errr... I was wrong. Bummer ;-). Sorry for the confusion. Deleted. – Peter - Reinstate Monica Nov 09 '20 at 13:43
  • @Peter-ReinstateMonica No worries! It was poorly explained by me :) – forsb Nov 09 '20 at 13:48
  • @chux-ReinstateMonica Thanks for the advice, wouldn't free(NULL) generate valgrind errors? It's not likely that the issue lays with the realloc stack function since the porblem occures before size matches capacity – forsb Nov 09 '20 at 13:51
  • @forsb The C spec has with `free()`, "If ptr is a null pointer, no action occurs". – chux - Reinstate Monica Nov 09 '20 at 15:01

2 Answers2

3

strdup is basically this (no error checking for brevity):

char *strdup(const char *stringtoduplicate)
{
  char *newstring = malloc(strlen(stringtoduplicate) + 1);
  strcpy(newstring, stringtoduplicate);
  return newstring;
}

You use it like this:

char Foo[] = "Bar";
char *newBar = strdup(Foo);
Foo[0] = 'F';
printf("%s %s\n", Foo, newBar);   // prints: Far Bar
...
free(newBar);     // once you're done with newBar, free it

Now you should be able to answer your own question.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • Thanks for your answer, s->data corresponds to char **. Will change it in the question – forsb Nov 09 '20 at 13:31
  • The OP's code looks ok to me, provided the function is mutex-protected and realloc_stack() does what it's supposed to. Why do you think the OP's program does not work? – Peter - Reinstate Monica Nov 09 '20 at 13:32
  • @forsb `strdup`, `strcpy`and `malloc` don't change the source string (why should they?). I suspect you have multithreading problems (poor or non existant synchronisation between threads) – Jabberwocky Nov 09 '20 at 13:34
1

strdup does not in any way modify its argument. If you look at the prototype for strdup you will see that its parameter is declared const, which means that it is not modified.

strdup can be implemented as:

char* strdup(const char* s) {
    char* n = malloc(strlen(s) + 1);
    if (n) strcpy(n, s);
    return n;
}

There is no magic.

You can use strcpy with threads, by the way. But strdup works fine.

rici
  • 234,347
  • 28
  • 237
  • 341