ComplicatedPhenomenon
ComplicatedPhenomenon

Reputation: 4199

Program terminated with signal SIGSEGV, Segmentation fault

I got a code snippet https://leetcode.com/problems/letter-combinations-of-a-phone-number/discuss/397542/C-solution

I submit it online, and it passed the test. Yet when I want to test on my local machine, I met a problem "Program terminated with signal SIGSEGV, Segmentation fault. " when it reach the next line of breakpoint - return result.

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

void catRes(char **result, char **phone, char *digits, char *tmp, int nowIndex, 
             int *resLen) {
    
    if (nowIndex == strlen(digits)) {
        tmp[nowIndex] = 0;
        result[(*resLen)] = (char *)malloc(strlen(tmp) + 1);
        strcpy(result[(*resLen)], tmp);
        (*resLen)++;
        return;
        
    }
    char *phoneData = phone[digits[nowIndex] - '0' - 2];
    for (int i = 0; i < strlen(phoneData); i++) {
        tmp[nowIndex] = phoneData[i];
        catRes(result, phone, digits, tmp, nowIndex + 1, resLen);
    }
}

char ** letterCombinations(char * digits, int* returnSize){
    char *phone[8] = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    char **result = (char **)malloc(sizeof(char *) * 40);
    char tmp[strlen(digits) + 1];
    int resLen = 0;
    if (strlen(digits) == 0) {
        *returnSize = resLen;
        return result;
    }
    catRes(result, phone, digits, tmp, 0, &resLen);
    *returnSize = resLen;// set breakpoint here
    return result;
}


int main(){
    char s[] = {'2', '3'};
    char * digits = s;
    int * returnSize = NULL;
    char ** outcome = letterCombinations(digits, returnSize);
    ...
    return 0;

I check the value of result at the line just before return result, it seems okay. I need some help to show me where the problem is.

Upvotes: 1

Views: 14402

Answers (2)

bruno
bruno

Reputation: 32594

"Program terminated with signal SIGSEGV, Segmentation fault. " when it reach the next line of breakpoint - return result.

this is because main call letterCombinations with NULL for returnSize so in :

*returnSize = resLen;// set breakpoint here

you write at the address 0.


Anyway before you have a lot of undefined behaviors accessing non initialized values. For instance in main the array s only contains the characters '2' and '3' and is not terminated by the null character, so strlen(digits) has an undefined behavior reading after s, just do char s[] = "23"; to avoid that.

The result executing your program under valgrind :

pi@raspberrypi:/tmp $ valgrind ./a.out
==6789== Memcheck, a memory error detector
==6789== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6789== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==6789== Command: ./a.out
==6789== 
==6789== Conditional jump or move depends on uninitialised value(s)
==6789==    at 0x4866210: ??? (in /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so)
==6789== 
==6789== Conditional jump or move depends on uninitialised value(s)
==6789==    at 0x48662D4: ??? (in /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so)
==6789== 
==6789== Use of uninitialised value of size 4
==6789==    at 0x106B8: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Conditional jump or move depends on uninitialised value(s)
==6789==    at 0x10498: catRes (c.c:8)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Use of uninitialised value of size 4
==6789==    at 0x10570: catRes (c.c:18)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Conditional jump or move depends on uninitialised value(s)
==6789==    at 0x10498: catRes (c.c:8)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Use of uninitialised value of size 4
==6789==    at 0x10570: catRes (c.c:18)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Conditional jump or move depends on uninitialised value(s)
==6789==    at 0x10498: catRes (c.c:8)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Use of uninitialised value of size 4
==6789==    at 0x10540: catRes (c.c:16)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Invalid read of size 4
==6789==    at 0x10540: catRes (c.c:16)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789==  Address 0xbd9670d0 is on thread 1's stack
==6789==  24 bytes below stack pointer
==6789== 
==6789== Use of uninitialised value of size 4
==6789==    at 0x10570: catRes (c.c:18)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Conditional jump or move depends on uninitialised value(s)
==6789==    at 0x10498: catRes (c.c:8)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Use of uninitialised value of size 4
==6789==    at 0x104AC: catRes (c.c:9)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Conditional jump or move depends on uninitialised value(s)
==6789==    at 0x48661D8: ??? (in /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so)
==6789== 
==6789== Use of uninitialised value of size 4
==6789==    at 0x48661DC: ??? (in /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so)
==6789== 
==6789== Conditional jump or move depends on uninitialised value(s)
==6789==    at 0x484762C: malloc (vg_replace_malloc.c:309)
==6789==    by 0x104DB: catRes (c.c:10)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Use of uninitialised value of size 4
==6789==    at 0x484BA2C: strcpy (vg_replace_strmem.c:513)
==6789==    by 0x10507: catRes (c.c:11)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Use of uninitialised value of size 4
==6789==    at 0x484BA48: strcpy (vg_replace_strmem.c:513)
==6789==    by 0x10507: catRes (c.c:11)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Conditional jump or move depends on uninitialised value(s)
==6789==    at 0x484BA80: is_overlap (vg_replace_strmem.c:131)
==6789==    by 0x484BA80: strcpy (vg_replace_strmem.c:513)
==6789==    by 0x10507: catRes (c.c:11)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Conditional jump or move depends on uninitialised value(s)
==6789==    at 0x484BA88: is_overlap (vg_replace_strmem.c:140)
==6789==    by 0x484BA88: is_overlap (vg_replace_strmem.c:127)
==6789==    by 0x484BA88: strcpy (vg_replace_strmem.c:513)
==6789==    by 0x10507: catRes (c.c:11)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Conditional jump or move depends on uninitialised value(s)
==6789==    at 0x484BA8C: is_overlap (vg_replace_strmem.c:143)
==6789==    by 0x484BA8C: is_overlap (vg_replace_strmem.c:127)
==6789==    by 0x484BA8C: strcpy (vg_replace_strmem.c:513)
==6789==    by 0x10507: catRes (c.c:11)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Conditional jump or move depends on uninitialised value(s)
==6789==    at 0x484BAA8: strcpy (vg_replace_strmem.c:513)
==6789==    by 0x10507: catRes (c.c:11)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x1059B: catRes (c.c:19)
==6789==    by 0x106D3: letterCombinations (c.c:32)
==6789==    by 0x1072B: main (c.c:42)
==6789== 
==6789== Invalid write of size 4
==6789==    at 0x106DC: letterCombinations (c.c:33)
==6789==    by 0x1072B: main (c.c:42)
==6789==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==6789== 
==6789== 
==6789== Process terminating with default action of signal 11 (SIGSEGV)
==6789==  Access not within mapped region at address 0x0
==6789==    at 0x106DC: letterCombinations (c.c:33)
==6789==    by 0x1072B: main (c.c:42)
==6789==  If you believe this happened as a result of a stack
==6789==  overflow in your program's main thread (unlikely but
==6789==  possible), you can try to increase the size of the
==6789==  main thread stack using the --main-stacksize= flag.
==6789==  The main thread stack size used in this run was 8388608.
==6789== 
==6789== HEAP SUMMARY:
==6789==     in use at exit: 304 bytes in 37 blocks
==6789==   total heap usage: 37 allocs, 0 frees, 304 bytes allocated
==6789== 
==6789== LEAK SUMMARY:
==6789==    definitely lost: 0 bytes in 0 blocks
==6789==    indirectly lost: 0 bytes in 0 blocks
==6789==      possibly lost: 0 bytes in 0 blocks
==6789==    still reachable: 304 bytes in 37 blocks
==6789==         suppressed: 0 bytes in 0 blocks
==6789== Rerun with --leak-check=full to see details of leaked memory
==6789== 
==6789== Use --track-origins=yes to see where uninitialised values come from
==6789== For lists of detected and suppressed errors, rerun with: -s
==6789== ERROR SUMMARY: 649 errors from 23 contexts (suppressed: 0 from 0)
Erreur de segmentation
pi@raspberrypi:/tmp $ 

Upvotes: 3

user14060819
user14060819

Reputation:

I added the missing } at the end of the main function and started fiddling with your code for a while. At the line

    char ** outcome = letterCombinations(digits, returnSize);

in your main function, you pass returnSize as a NULL. Now shortly before returning from you letterCombinations function, you try to dereference said NULL and this is what causes a SEGFAULT.

Now it seems like you are trying to propagate a value from inside of your letterCombinations function to the outside. One would do this by passing the pointer to a valid variable to the function like so:

int main(){
    char s[] = {'2', '3'};
    char * digits = s;
    int returnSize;
    char ** outcome = letterCombinations(digits, &returnSize);
    return 0;
}

Regarding why it passed the online-test, I cannot answer this as fast as your main question.

Upvotes: 2

Related Questions