newBike newBike - 1 month ago 18
C Question

How to use lldb to debug the segmentation fault

I got this exception by running LLDB for my program.

However, the exception didn't give me any concrete clues for finding the root cause.

Of course, based on experience, I might access the memory not correctly.

Any idea to find the root cause by LLDB? Thanks

continue to play (y/n)? y
Process 30020 stopped
* thread #1: tid = 0x24b72, 0x00007fff893c8365 libsystem_platform.dylib`_platform_strncmp + 325, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x79)
frame #0: 0x00007fff893c8365 libsystem_platform.dylib`_platform_strncmp + 325
libsystem_platform.dylib`_platform_strncmp:
-> 0x7fff893c8365 <+325>: movzbq (%rsi,%rcx), %r8
0x7fff893c836a <+330>: subq %r8, %rax
0x7fff893c836d <+333>: jne 0x7fff893c837d ; <+349>
0x7fff893c836f <+335>: testq %r8, %r8
(lldb)
error: No auto repeat.


code



#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <memory.h>

const int USER_INPUT_SIZE_EACH_LINE = 999;

void draw_middle_lines(char *middle_line, int width) {
printf("%s", middle_line);
for (int i = 2; i < width; i++) {
printf(" ");
}
printf("%s\n", middle_line);
}

void draw_bound_line(char *bound_char, int width) {
for (int i = 0; i < width; i++) {
printf("%s", bound_char);
}
printf("\n");
}


void clearNewline(char *line, int max_len) {
for (int i = 0; i < max_len; i++) {
if (line[i] == '\n') {
line[i] = '\0';
}
}
}

char **ask_user_preference() {
const int NUM_OF_PROMPTS = 4;
char *prompt[] = {
"please input height:",
"please input width:",
"please input horizontal char:",
"please input vertical char:",
};
char **preference;
preference = malloc(NUM_OF_PROMPTS);
for (int i = 0; i < NUM_OF_PROMPTS; i++) {
preference[i] = malloc(USER_INPUT_SIZE_EACH_LINE);
memset(preference[i], 0, sizeof(char) * USER_INPUT_SIZE_EACH_LINE);
printf("%s", prompt[i]);
fgets(preference[i], USER_INPUT_SIZE_EACH_LINE, stdin);
clearNewline(preference[i], USER_INPUT_SIZE_EACH_LINE);
}
return preference;
}

void draw(int w, int h, char *bound_char, char *middle_char) {
draw_bound_line(bound_char, w);
for (int i = 2; i < h; i++) {
draw_middle_lines(middle_char, w);
}
draw_bound_line(bound_char, w);
}

void clr_input_buffer() {
for (;;) {
int c = getchar();
if (c == EOF || c == '\n')
break;
}

}

int main() {
char *cont;
do {
char **pref = ask_user_preference();
int height = atoi(pref[0]);
int width = atoi(pref[1]);
char *bound_char = pref[2];
char *middle_char = pref[3];
draw(width, height, bound_char, middle_char);
printf("continue to play (y/n)? ");
fgets(cont, 10, stdin);
if (strncmp(cont, 'y', 1) != 0) {
break;
}
} while (1);
printf("BYE BYE~");
return 0;
}

Answer

The function call

strncmp(cont, 'y', 1)

will likely cause a segfault, because 'y' is a character value passed as a memory location. I suggest

strncmp(cont, "y", 1)

although I am unsure of the sense of of your comparison. Anyway I suggest this would be better

toupper(cont[0]) == 'Y'

and I leave the sense of the comparison to you. Finally please enable all compiler warnings which would have caught this.