1

I'm trying to use a function to assign space and fill that space (or at least some of it) with characters to form a string. Within the function I make a call to malloc, and within the same function I assign characters to the given space. The following code gives the general gist of what I'm doing:

#define INITIAL 10

int func(char **s);

int
main(int argc, char **argv) {
    char *s;
    int n;

    n = func(&s);
    printf("Done\n");

    return 0;
}

int
func(char **s) {
    int i;

    *s = (char*)malloc(INITIAL*sizeof(char));
    assert(*s);

    for (i=0; i<5; i++) {
        printf("i=%d\n", i);
        *s[i] = 'a'; /*'a' is an arbitrary char for this example */  
    }
    return i;    
}

The output of this code is:

i=0
i=1
i=2
Segmentation fault: 11

The reason I have my function return an int is because I ultimately want the function to return the length of the string I have formed.
I'm completely unsure why I am getting a segmentation fault; it seems I have assigned enough space to fit the next char in. It also seems weird to me that it stops at i=2. If anyone could identify the mistakes I have made I would greatly appreciate it!

3
  • Can't you use strdup or asprintf (on Linux, you could)? Don't forget to compile your code with all warnings & debug ino (gcc -Wall -Wextra -g if using GCC...). Use a debugger (gdb) & valgrind; avoid undefined behavior Commented Oct 3, 2015 at 14:20
  • You should add free(s); before return 0; or your program will create a memory leak Commented Oct 3, 2015 at 16:36
  • Curious: what suggest using *sizeof(char) in malloc(INITIAL*sizeof(char)) as sizeof(char) is always 1? Nice: alternative: *s = malloc(INITIAL* sizeof *(*s)); Commented Oct 3, 2015 at 21:39

4 Answers 4

5

Instead of

*s[i] = 'a';

you want

(*s)[i] = 'a';

*s[i] is equivalent to *(s[i]). That is, it treats s as an array of strings and gives you the first character of the string at index i.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot! All fixed :)
2

*s[i] first calculate s[i], which won't be valid place for i!=0, then dereference it and try to put 'a' there. It may cause Segmentation Fault.

Try changing *s[i] to (*s)[i].

1 Comment

Thanks for your help!
1

Postfix [] has higher precedence than unary *, so *s[i] is being parsed as *(s[i]), which isn't what you want; you want to dereference s and index into the result, so you need to explicitly group the * operator with s: (*s)[i].

1 Comment

Thanks a lot John, appreciate the help :)
0

You may want to use size_t instead of an int. Or ssize_t if you need the function to return a negative value:

#include <stdio.h>
#include <stdlib.h>
#define INITIAL 10

ssize_t func(char **);

int main(void)
{
    char *s;

    if((func(&s)) == -1)
    {
        printf("An error occurred\n");
        return 1;
    }

    printf("Done\n");

    free(s);
    return 0;
}


ssize_t func(char **s)
{
    size_t i = 0;

    if ( INITIAL < 1 )
            return -1;

    if (!(*s = malloc(INITIAL*sizeof(char))))
            return -1;

    for (i=0; i< 5; i++) {
        printf("i=%zu\n", i);
        (*s)[i] = 'a';; /*'a' is an arbitrary char for this example */
    }
    return i;
}

2 Comments

Note: ssize_t is not defined in standard C. Common extension though.
If you don't mind me asking what would be the benefit of doing this? I'm fairly new to C and my textbook only briefly mentions size_t, and doesn't specify how it is different to int.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.