简体   繁体   中英

Segmentation fault while using pointer to pointer to a char

While compiling and executing the below program i am getting a warning during compilation and seg fault during execution.

Warning

program.c: In function main:
program.c:17: warning: passing argument 2 of convertString from incompatible pointer type

line 17 is the call to convertString(input, &output);

attaching the debugger is can see the segfault is occuring at the below line

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400521 in convertString (input=0x7fffffffd100 "abcdefg", output=0x7fffffffd0f0) at program.c:9
9           **output = *input;
(gdb) s

#include<stdio.h>
#include<string.h>
void convertString(char *input, char **output)
{
    if(strlen(input)== 0)
    {
        return;
    }
    **output = *input;
    (*output)++;
    convertString(input+1,output);
}
int main()
{
    char input[] = "abcdefg";
    char output[sizeof(input)];
    convertString(input, &output);
    printf("%s", output);
    return 0;
}

Please help me where i am doing wrong.

The problem is that output is not a pointer, it's an array, and using the address-of operator on an array gives you a (single) pointer to the array (in your case of type char (*)[8] ). For clarification: (void *) output == (void *) &output , both the decayed pointer of the array, and the pointer to the array, are equal.

So you're not really passing a pointer to a pointer to char to the function.


Besides the above, I see no reason that the function should take a pointer to a pointer, a plain single pointer should be enough. Otherwise you will get wrong result when using output in the printf call as then output would point beyond the end of the string.

Also, you don't terminate the output string.

You do not really need a double pointer to the output buffer here, a plain char* suffices:

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

void convertString(char *input, char *output)
{
    if(!(*output = *input)) // Copy the zero terminator as well.
        return;
    convertString(input + 1, output + 1);
}

int main()
{
    char input[] = "abcdefg";
    char output[sizeof(input)];
    convertString(input, output);
    printf("%s", output);
    return 0;
}

Character array output has type char [sizeof( "abcdefg" ) ] that is equivalent to char[8] . So expression &output in function call

convertString(input, &output);

has type char ( * )[8] while the corresponding parameter of the function has type char ** . They are incompatible types and the compiler points to this mistake.

There is no sense to declare this parameter as having type char ** . It has to be declared like char * .

void convertString(char *input, char *output);

Also within the function the terminating zero is not copied from the input string to the output string. The function simply exits.

if(strlen(input)== 0)
{
    return;
}

And it is inefficient to calculate the length of the string in each recursion. You could substitute this condition at least for

if ( input[0] == '\0' )

or

if ( *input == '\0' )

or

if ( !*input )

Also it is unclear why the function is named convertString instead of for example copyString .

Take into account that there is a common convention that string functions return pointers to strings they process. The function can be defined simpler.

Here is a demonstrative program

#include <stdio.h>

char * copyString( char *output, const char *input )
{
    if ( ( *output = *input ) ) copyString( output + 1, input + 1 );
    return output;
}

int main(void) 
{
    char input[] = "abcdefg";
    char output[sizeof(input)];

    puts( copyString( output, input ) );    

    return 0;
}

The program output is

abcdefg

The issue, as aleardy pointed out by Mr. JP in his answer , is &output does not give you a char ** , it gives a char (*)[8] in this case, which will decay into a char * when used as function argument.

In your case, you don't need a pointer-to-pointer to alter the contents of the memory area pointed by that pointer. A simple pointer will do. You can change

void convertString(char *input, char **output)

to

void convertString(char *input, char *output)  //output is of type char*

and other occurrences of output similarly and call it like

convertString(input, output);

that should work.

That said, you should null-terminate output to make it use as a string .

#include<stdio.h>
#include<string.h>
void convertString(char *input, char *output)
{
    if(strlen(input)== 0)
    {
        return;
    }
    *output = *input;
    output++;
    convertString(input+1,output);
}
int main()
{
    char input[] = "abcdefg";
    char output[sizeof(input)];
    convertString(input, output);
    printf("%s\n", output);
    return 0;
}

Probably this is what you wanted to do?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM