user3403424
user3403424

Reputation: 11

Segmentation Fault when i do assign a value in an array in a funtion

I did debug the program, and the segmentation fault does appear in when I do a[k] = a[h]. The array a is a dinamic array, so I can't understand where is the problem... Can you help me?

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

void Invert(char* a, int k, int h) {
    if(k < h) {
        char app;
        app = a[k];
        a[k] = a[h]; //here is the error
        a[h] = app;
        Invert(a,k+1,h-1);
        }
}

void CallInvert(char* a, char k) {
    int n = strlen(a);
    Invert(a, k, n-1);
}


int main(int argc, char *argv[]) {
    char *a; int k,i;
    a = malloc(sizeof(char)*sizeof("Hi, how are you?"));
    a = "Hi, how are you?";
    k = 5;
    if(k>=strlen(a)) {
        printf("ERROR");
        return 0;
    }
    printf("Before: \"%s\"\n", a);
    CallInvert(a,k);
    printf("After: \"%s\"\n",a);
    free(a);
    return 0;
}

Upvotes: 0

Views: 1646

Answers (5)

user1969104
user1969104

Reputation: 2420

In main(), a = "Hi, how are you?" is wrong. You are assigning a pointer to a constant string here. Later when you try to write to the constant string it will crash (As iharob pointed out below, writing to a constant string more specifically termed as causing an 'undefined behavior'; which happens to be a segmentation fault in your platform).

Upvotes: 2

user539810
user539810

Reputation:

Your problem results from assigning a string literal to your pointer, which overwrites the address returned by malloc. This also means that your call to free will trigger undefined behavior, such as a segfault, because you're effectively doing this:

char *a;
a = "Hi, how are you?";
free (a);

You also cannot free the memory to which malloc returned a pointer. This means you have a memory leak.

As others have stated, you want to copy the string using strcpy:

a = malloc (sizeof "Hi, how are you?");
strcpy (a, "Hi, how are you?");

Then things should work fine.

Ignore the people who don't know how to use sizeof in this context. They likely don't know, until now, that a string literal is considered an array of characters, plus 1 extra character slot for the null terminator, not just a pointer to such an array. You can use strlen and add 1 to it if you like, but this fails when you have embedded null characters, unlike the sizeof operator:

#define HELLO "Hello\0World!"
printf (
    "%zu\n%zu\n",
    sizeof HELLO,
    strlen (HELLO) + 1
);

Plus I just don't like calling a function and performing arithmetic when the compiler can do it for me without that overhead.

However, once you assign a string literal to a pointer, you remove any size information, which is probably where the misconception about sizeof and string literals comes from. In such a case, using strlen is safer. To be fair, I'm not aware of any code that actually embeds null characters in string literals that function as operands to sizeof operators.

Upvotes: 0

I tried executing several times and did not find the problem in the line you have mentioned above, now my code looks like this:

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

void Invert(char* a, int k, int h) {
    if (k < h) {
        char app;
        app = a[k];
        a[k] = a[h];
        a[h] = app;
        Invert(a, k + 1, h - 1);
    }
}

void CallInvert(char* a, char k) {
    int n = strlen(a);
    Invert(a, k, n - 1);
}

int main(int argc, char *argv[]) {
    char *a = NULL; 
    int k;
    a = (char *)malloc(sizeof(char)*strlen("Hi, how are you?") + 1);
    strcpy(a, "Hi, how are you?");
    k = 5;
    if (k >= strlen(a)) {
        printf("ERROR");
        return 0;
    }
    printf("Before: \"%s\"\n", a);
    CallInvert(a, k);
    printf("After: \"%s\"\n", a);
    free(a);
    return 0;
}

It seems to work fine and produced the output:

Before: "Hi, how are you?"

After: "Hi, h?uoy era wo"

Here are some changes that i have made:

  1. Used strlen to get the length of string, and strcpy to copy string, but I see that it has already been captured in comment, I am leaving it here for clarity.
  2. Typecasted return value of malloc to char *, as Visual studio was throwing error. This actually depends on what platform you are running on.

Upvotes: 0

VolAnd
VolAnd

Reputation: 6407

See my changes in the peace of code for memory allocation:

    a = (char*)malloc(sizeof(char)* (sizeof("Hi, how are you?") + 1) );
    strcpy(a,"Hi, how are you?");

sizeof("Hi, how are you?") works correctly, but to store '\0' (end of string) you need one more character. And of course strcpy or strncpy for copying characters to modifiable memory.

Upvotes: 0

RadijatoR
RadijatoR

Reputation: 113

You need to use strcpy function. Like:

a = malloc(sizeof(char)*sizeof("Hi, how are you?"));
    strcpy(a ,"Hi, how are you?");

SEGFAULT is cause you can't change value constat literal.

Upvotes: 0

Related Questions