1
typedef struct element element;
struct element{
    dado_t str;
    elemento* preview;
    elemento* next;
};

typedef struct lista2 lista2;
struct lista2{
    elemento* primeiro;
    elemento* ultimo;
    elemento* corrente;
};


void caller(lista2* l){
    char *s = l->corrente->str;
    char *s2 = l->corrente->next->str;
    my_func(&s, &s2);
}

void my_func(char **s, char**s2){
    size_t len = strlen(*s);
    size_t len2 = strlen(*s2);
    char *w = *s;
    char *tmp = realloc(w, len + len2 + 1); //PROBLEM HERE
    if(tmp != NULL)
       *s = tmp;
    else
        *s = NULL;
    strcat(*s, *s2);
}  

When I run my code(before realloc()):

  • *w = "I Like Coffe" with memory adress: 0x605050
  • *s = "I Like Coffe" with memory adress: 0x605050
  • l->corrente->str = "I Like Coffe" with memory adress: 0x605050

All good so far.
Now status after realloc(Before the assign *s = tmp):

  • *w = "" with memory adress: 0x605050
  • *s = "" with memory adress: 0x605050
  • l->corrente->str = "" with memory adress: 0x605050

Still ok, right ? Now what I get after *s = tmp:

  • *w = "" with memory adress: 0x605050
  • *s = "I Like Coffe" with memory adress: 0x605160 CHANGED
  • l->corrente->str = "" with memory adress: 0x605050

What I need:
1) Change l->corrente->str value in my_func();
2) Or somehow, change *s value to the new value after strcat. And keep l->corrente->str the same.

PlayHardGoPro
  • 2,791
  • 10
  • 51
  • 90
  • You make `*s` `NULL` and then do `strcat(*s ...)` why? the whole point is to prevent undefined behavior which you are invoking, rather you should `free(*s)`. Also, I don't get your question, where in your code is `*s = "I Like Coffe"`? may be you need some Coffe? ;) – Iharob Al Asimi May 15 '15 at 02:50
  • `*s = l->corrente->str`. And `l->corrente->str` = "I Like Coffe". I just think there is no need to show another function. – PlayHardGoPro May 15 '15 at 02:53
  • Yes there is, there is a huge difference in the assignments you show above, if you use `realloc()` with `"I Like Coffe"`'s address then nothing good will happen, but you can't be sure what in fact it will be. – Iharob Al Asimi May 15 '15 at 02:54
  • See also [`realloc()` setting pointer to empty](http://stackoverflow.com/questions/30228331) for a variant of this code. – Jonathan Leffler May 15 '15 at 04:07
  • dado_t not defined, elemento not defined. Please fix these items then add the required #include statements for the header files. then repost the code. – user3629249 May 16 '15 at 01:54
  • with out the necessary surrounding code, especially exactly how the parameters passed to my_func() are declared in the calling function, the posted code will be very difficult to debug. My first guess is that parameter 's' is not pointing to memory allocated via any of the malloc() family of functions. – user3629249 May 16 '15 at 01:57
  • a struct should (almost always) never be typedef'd. the typedef'ing just clutters the code, makes it more difficult for humans to read, and clutters the compiler name space; especially since the typedef'd name is the same as the tag name of the struct. – user3629249 May 16 '15 at 01:59

1 Answers1

1

If I understand you correctly and you want to create a concatenated value while keeping *s or l->corrente->str the same, then it would make more sense to have my_func return a pointer to the new concatenated string while keeping both input strings unchanged. If I don't understand what your are attempting to do, please leave a comment.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *my_func(char *s, char*s2);

int main (void) {

    char *a = strdup ("I like coffee.");
    char *b = strdup ("I like tea.");

    char *c = my_func (a, b);

    printf ("\n a: %s\n b: %s\n c: %s\n\n", a, b, c);

    return 0;
}

char *my_func(char *s, char*s2)
{
    size_t len = strlen(s);
    size_t len2 = strlen(s2);
    char *w = strdup (s);

    char *tmp = realloc(w, len + len2 + 1); //PROBLEM HERE

    if(!tmp) {
        fprintf (stderr, "%s() error: realloc failed.\n", __func__);
        return NULL;
    }

    w = tmp;
    strcat(w, s2);

    return w;
}

Output

$ ./bin/realloc_post

 a: I like coffee.
 b: I like tea.
 c: I like coffee.I like tea.

void - preserving *s, concatenate in *s2

Instead of returning a pointer, this implementation of my_func remains void and takes s and s2, keeping s unchanged, but concatenating "ss2" in s2. If I misunderstood again, let me know.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void my_func(char **s, char **s2);

int main (void) {

    char *a = strdup ("I like coffee.");
    char *b = strdup ("I like tea.");

    my_func (&a, &b);

    printf ("\n a: %s\n b: %s\n\n", a, b);

    free (a);
    free (b);

    return 0;
}

void my_func(char **s, char **s2)
{
    size_t len = strlen(*s);
    size_t len2 = strlen(*s2);
    char *w = strdup (*s);
    char *p = *s2;          /* save start address to free */

    char *tmp = realloc(w, len + len2 + 1);

    if(!tmp) {
        fprintf (stderr, "%s() error: realloc failed.\n", __func__);
        return;
    }

    strcat(tmp, *s2);
    *s2 = tmp;
    free (p);
}

Output

$ ./bin/realloc_post

 a: I like coffee.
 b: I like coffee.I like tea.
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • I can't change the void type. And yes I want to concatenate `s` and `s2`. Put the whole `s2` string in the end of `s2`. – PlayHardGoPro May 15 '15 at 03:18
  • @PlayHardGoPro, OK, I have rewritten `my_func` as `void` to **"Put the whole s2 string in the end of s2"**. If I missed the mark again, let me know. I think I understood you this time. – David C. Rankin May 15 '15 at 03:29
  • Nice! Never heard of this `strdup()`. But one strange thing happen. When I do `strdup()` it gives `w` address *X* then when I make `realloc` it gives the same *X* address to `char *tmp`. Apparently it worked (I'll test), but is that normal ? – PlayHardGoPro May 15 '15 at 03:38
  • 1
    Yes. `strdup` is an **allocate, then copy** function that duplicates the string in a new address. When you `realloc` you can get a new address or the same address depending on whether sufficient space exists at the end of the current block of memory. So that may or may not happen. Basically all I did was make a copy of `s` in `w`, then `realloc`'ed `w` and concatenated `s2` on the end, then assigned `s2` the new pointer. – David C. Rankin May 15 '15 at 03:40
  • You Rock ! Thanks David. Worked Perfect ! – PlayHardGoPro May 15 '15 at 03:45
  • Glad I could help. See the updated version -- I added a pointer to free the original `s2` to prevent a memory leak `:p` – David C. Rankin May 15 '15 at 03:47
  • OP, regarding your statement: ' I want to concatenate s and s2. Put the whole s2 string in the end of s2' The posted code is trying to put the whole s2 string at the end of s. please clarify – user3629249 May 16 '15 at 02:05