Segmentation Fault in function that changes the values of 2 strings

2

The following function changes (or at least should) the content of two strings

void trocar(char *a, char *b){
    char *novo = (char *) malloc(sizeof(char) * 10);

    strcpy(novo, a);
    strcpy(a, b);
    strcpy(b, novo);
}

But when calling the function in main, Segmentation Fault occurs.

int main(int argc, char const *argv[]) {

    char *a = "oi";
    char *b = "tchau";
    trocar(a, b);
    printf("a: %s, b: %s\n", a, b);

    return 0;
}

I could not understand what is causing this error.

What causes this? And if possible, how would a function change the value of two strings correctly?

    
asked by anonymous 19.11.2018 / 05:17

1 answer

2

You did not copy to the area of your code, so you tried to swap values from the static area of the code and this is a read-only area. The data that is in your code is neither in automatic memory nor in dynamic memory which is what you want to move. This works:

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

void trocar(char *a, char *b) {
    char *novo = malloc(10);
    strcpy(novo, a);
    strcpy(a, b);
    strcpy(b, novo);
}

int main() {
    char *a = malloc(10);
    strcpy(a, "oi");
    char *b = malloc(10);
    strcpy(b, "tchau");
    trocar(a, b);
    printf("a: %s, b: %s\n", a, b);
}

See running on ideone . And no Coding Ground . Also I put it in GitHub for future reference .

But the way you actually change because it's more efficient would be to use only pointers:

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

void trocar(char **a, char **b) {
    char *novo = *a;
    *a = *b;
    *b = novo;
}

int main() {
    char *a = malloc(3);
    strcpy(a, "oi");
    char *b = malloc(6);
    strcpy(b, "tchau");
    trocar(&a, &b);
    printf("a: %s, b: %s\n", a, b);
}

See running on ideone . And no Coding Ground . Also I put it in GitHub for future reference .

But if you really want to change the value at least you should use automatic memory that is more secure and efficient, dynamic memory should be used in the latter case, and it does not seem necessary in this case (it would only be if you have something that you do not know only seeing this code). Then the dice is already putting where it should. But it still does copy which is still very inefficient.

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

void trocar(char *a, char *b) {
    char novo[10];
    strcpy(novo, a);
    strcpy(a, b);
    strcpy(b, novo);
}

int main() {
    char a[10] = "oi";
    char b[10] = "tchau";
    trocar(a, b);
    printf("a: %s, b: %s\n", a, b);
}

See running on ideone . And no Coding Ground . Also I put it in GitHub for future reference .

Note that in your example I had to change the memory allocation because with the exchange you have to ensure that everyone involved has room for the largest one. For a general example this is much more complicated, for this example the largest is 6, we are seeing in the code, but you used 10 in the temporary, I imagine you know what you are doing, that could change the code to be more than 6, but not more than 10 (9 usable characters). So I fixed that. And there in the allocation example in the stack I also had to use 10. Yes, there is a waste in both, which in this case changes little. So the second solution is also the best in this aspect of memory consumption, it's even more conceptually correct, it's not just efficiency.

    
19.11.2018 / 11:00