Welcome to the Builder Academy

Question Segmentation Fault.

More
25 Feb 2019 06:06 #8331 by timeba
Replied by timeba on topic Segmentation Fault.
Still running into the same error.

I replaced the code like suggested:
Code:
char *get_art(struct char_data *vict) { static char buf[200]; // char buf[200]; #### bug fix timeba 24 FEB 2019 #### *buf = '\0'; // char *fbuf = buf; #### bug fix timeba 24 FEB 2019 #### int art_num; int count; ... ... return buf; // return fbuf; #### bug fix timeba 24 FEB 2019 ####

This is the current gdb:
Code:
Program received signal SIGSEGV, Segmentation fault. 0x0000555555593f85 in perform_act (orig=0x5555555e24b1 "c >", ch=0x555556062450, obj=0x0, vict_obj=0x0, to=0x555556062450) at comm.c:2631 2631 while ((*buf = *(i++))) (gdb) bt #0 0x0000555555593f85 in perform_act (orig=0x5555555e24b1 "c >", ch=0x555556062450, obj=0x0, vict_obj=0x0, to=0x555556062450) at comm.c:2631 #1 0x00005555555b2aed in nanny (d=0x5555560606d0, arg=<optimized out>) at interpreter.c:1858 #2 0x00005555555972eb in game_loop (mother_desc=3) at comm.c:768 #3 0x0000555555597526 in init_game (port=<optimized out>) at comm.c:385 #4 0x00005555555613c6 in main (argc=1, argv=<optimized out>) at comm.c:332 (gdb) list 2626 log("SYSERR: Illegal $-code to act(): %c", *orig); 2627 log("SYSERR: %s", orig); 2628 i = ""; 2629 break; 2630 } 2631 while ((*buf = *(i++))) 2632 { 2633 if (uppercasenext && !isspace((int) *buf)) 2634 { 2635 *buf = UPPER(*buf); (gdb) info local k = "\003\000\000\000\000\000\000\000\341\274\377\377\377\177\000\000\000\000\000" i = 0x1 <error: Cannot access memory at address 0x1> lbuf = "<art ~ save\000/jax.alias", '\000' <repeats 59 times>, "\277\377\377\377\177\000\000$\016\362\366\377\177\000\000\220\275\377\377\377\177\000\000$\016\362\366\377\177\000\000\vh\b\000\000\000\000\000\005", '\000' <repeats 31 times>, "`b\322UUU\000\000\001\000\000\000\000\000\000\000\212\026\\UUU\000\000\000\277\377\377\377\177\000\000\027\335\\UUU\000\000\001\000\000\000\000\000\000\000"... buf = 0x7fffffffbce7 "save" j = <optimized out> uppercasenext = 0 '\000' (gdb) up #1 0x00005555555b2aed in nanny (d=0x5555560606d0, arg=<optimized out>) at interpreter.c:1858 1858 act("<art ~ $c >", FALSE, d->character, 0, 0, TO_CHAR); (gdb) info local load_room = <optimized out> load_result = 1 dt = <optimized out> clan_num = <optimized out> i = 0 (gdb) list 1853 GET_LOADROOM(d->character) = NOWHERE; 1854 1855 // save_char(d->character); // orig location, moving to AFTER NEWBIE CREATION -- heebie apr 22, 2013 1856 1857 act("<cha $x $h $i ~ $c ~ enters game $n ~ $z>", TRUE, d->character, 0, 0, TO_ROOM); 1858 act("<art ~ $c >", FALSE, d->character, 0, 0, TO_CHAR); 1859 1860 /* Put to sleep if they are affected. */ 1861 if (AFF_FLAGGED(d->character, AFF_SLEEP)) { 1862 send_to_char(d->character,"<sleep>\r\n"); (gdb) up #2 0x00005555555972eb in game_loop (mother_desc=3) at comm.c:768 768 nanny(d, comm); (gdb) info local input_set = {__fds_bits = {32, 0 <repeats 15 times>}} output_set = {__fds_bits = {32, 0 <repeats 15 times>}} exc_set = {__fds_bits = {0 <repeats 16 times>}} null_set = {__fds_bits = {0 <repeats 16 times>}} last_time = {tv_sec = 1551037692, tv_usec = 35864} opt_time = {tv_sec = 0, tv_usec = 100000} process_time = {tv_sec = 0, tv_usec = 1112} temp_time = {tv_sec = 0, tv_usec = 98888} before_sleep = {tv_sec = 1551037691, tv_usec = 936976} now = {tv_sec = 1551037692, tv_usec = 36493} timeout = {tv_sec = 0, tv_usec = 0} comm = "1\000x\000zaOqIl14\000\177\000\000 \233\036\367\377\177\000\000 \233\036\367\377\177\000\000\360\342\377\377\377\177\000\000\202\203]UUU\000\000\301\364r\\\000\000\000\000\000\202\034%\322\006\304X\000\000\000\000\000\000\000\000\003\000\000\000\000\000\000\000@\255^UUU\000\000\220\037\000\000\000\000\000\000\320\343\377\377\377\177\000\000c\204]UUU\000\000\b\000\000\000\060\000\000\000\340\343\377\377\377\177\000\000 \343\377\377\377\177\000\000\000\202\034%\322\006\304X\360\341\377\377\377\177\000\000\360\340\377\377\377\177\000\000\000\000\000\000\000\000\000\000G\335\360\366\377\177\000\000\340\342\377\377\377\177\000\000\300\242\376\367\377\177\000\000\001\000\000\000\000\000\000\000"... d = 0x5555560606d0 next_d = 0x0 pulse = <optimized out> missed_pulses = 0 maxdesc = <optimized out> aliased = 0 (gdb) list 763 string_add(d, comm); 764 else if (d->showstr_count) /* Reading something w/ pager */ 765 show_string(d, comm); 766 else if (STATE(d) != CON_PLAYING) { /* In menus, etc. */ 767 // mudlog(CMP, LVL_GRGOD, TRUE, "calling nanny on socket d comm.c line 767 "); 768 nanny(d, comm); 769 } 770 else { /* else: we're playing normally. */ 771 if (aliased) /* To prevent recursive aliases. */ 772 d->has_prompt = 1; /* To get newline before next cmd output. */ (gdb) up #3 0x0000555555597526 in init_game (port=<optimized out>) at comm.c:385 385 game_loop(mother_desc); (gdb) info local mother_desc = 3 (gdb) list 380 /* If we made it this far, we will be able to restart without problem. */ 381 remove(KILLSCRIPT_FILE); 382 383 log("Entering game loop."); 384 385 game_loop(mother_desc); 386 387 Crash_save_all(); 388 //House_save_all(); /* obsolete - SMD 2007-01-16 */ 389 (gdb) up #4 0x00005555555613c6 in main (argc=1, argv=<optimized out>) at comm.c:332 332 init_game(port); (gdb) info local port = 8080 pos = <optimized out> dir = 0x5555555ead40 "lib" (gdb) list 327 328 if (scheck) 329 boot_world(); 330 else { 331 log("Running game on port %d.", port); 332 init_game(port); 333 } 334 335 log("Clearing game world."); 336 destroy_db(); (gdb) up Initial frame selected; you cannot go up. (gdb) quit

Please Log in or Create an account to join the conversation.

More
25 Feb 2019 23:17 #8332 by thomas
Replied by thomas on topic Segmentation Fault.
hmm. This is strange. Now, the get_art function should work correctly. Apparently, it can only return a pointer to a legal buffer now.

Would you mind sharing the full perform_act() function?
Somewhere there, you're setting i to something not-correct, either through direct assignment (though, you'd probably have noticed it by now) or by buffer overrun.

Please Log in or Create an account to join the conversation.

More
26 Feb 2019 06:21 #8333 by timeba
Replied by timeba on topic Segmentation Fault.
Here is perform_act
Code:
char *ACTNULL = "<NULL>"; #define CHECK_NULL(pointer, expression) \ if ((pointer) == NULL) i = ACTNULL; else i = (expression); /* higher-level communication: the act() function */ void perform_act(char *orig, struct char_data *ch, struct obj_data *obj, void *vict_obj, struct char_data *to) { register char *i = NULL, *buf; static char lbuf[MAX_STRING_LENGTH]; buf = lbuf; for (;;) { if (*orig == '$') { switch (*(++orig)) { case 'n': i = PERS(ch, to); break; case 'N': CHECK_NULL(vict_obj, PERS((struct char_data *) vict_obj, to)); break; case 'm': i = HMHR(ch); break; case 'M': CHECK_NULL(vict_obj, HMHR((struct char_data *) vict_obj)); break; case 's': i = HSHR(ch); break; case 'S': CHECK_NULL(vict_obj, HSHR((struct char_data *) vict_obj)); break; case 'e': i = HSSH(ch); break; case 'E': CHECK_NULL(vict_obj, HSSH((struct char_data *) vict_obj)); break; case 'o': CHECK_NULL(obj, OBJN(obj, to)); break; case 'O': CHECK_NULL(vict_obj, OBJN((struct obj_data *) vict_obj, to)); break; case 'p': CHECK_NULL(obj, OBJS(obj, to)); break; case 'P': CHECK_NULL(vict_obj, OBJS((struct obj_data *) vict_obj, to)); break; case 'a': CHECK_NULL(obj, SANA(obj)); break; case 'A': CHECK_NULL(vict_obj, SANA((struct obj_data *) vict_obj)); break; case 'T': CHECK_NULL(vict_obj, (char *) vict_obj); break; case 'F': CHECK_NULL(vict_obj, fname((char *) vict_obj)); break; case '$': i = "$"; break; default: log("SYSERR: Illegal $-code to act(): %c", *orig); log("SYSERR: %s", orig); break; } while ((*buf = *(i++))) buf++; orig++; } else if (!(*(buf++) = *(orig++))) break; } *(--buf) = '\r'; *(++buf) = '\n'; *(++buf) = '\0'; SEND_TO_Q(CAP(lbuf), to->desc); }

Please Log in or Create an account to join the conversation.

More
26 Feb 2019 21:47 - 26 Feb 2019 21:48 #8334 by thomas
Replied by thomas on topic Segmentation Fault.
But... in this comment: www.tbamud.com/forum/4-development/4478-segmentation-fault#8329 you wrote about the %c and %C cases, and they're not here, now.

In that last comment it looks almost like the stock version, apart from a missing line:
Code:
default: log("SYSERR: Illegal $-code to act(): %c", *orig); log("SYSERR: %s", orig); + i = ""; break;
Last edit: 26 Feb 2019 21:48 by thomas.

Please Log in or Create an account to join the conversation.

More
27 Feb 2019 00:03 #8335 by timeba
Replied by timeba on topic Segmentation Fault.
I had the stock and production code opened side by side and accidentally copied the stock code haha.

Here is the production code:
Code:
const char *ACTNULL = "<NULL>"; #define CHECK_NULL(pointer, expression) \ if ((pointer) == NULL) i = ACTNULL; else i = (expression); /* higher-level communication: the act() function */ void perform_act(const char *orig, struct char_data *ch, struct obj_data *obj, const void *vict_obj, const struct char_data *to) { char k[20]; const char *i = NULL; char lbuf[MAX_STRING_LENGTH], *buf, *j; bool uppercasenext = FALSE; buf = lbuf; for (;;) { if (*orig == '$') { switch (*(++orig)) { case 'r': /* get random number */ sprintf(k, "%i", rand_number(1, 9999999)); i = k; break; case 'c': /* get character art */ i = get_art(ch); break; case 'C': /* get victim art */ i = get_art((struct char_data *) vict_obj); break; case 'z': /* affects */ sprintf(k, " %ld", AFF_FLAGS(ch)); if (AFF_FLAGGED(to, AFF_DETECT_ALIGN)) { if (IS_EVIL(ch)) strcat(k, " evil"); //heebie orig: strcpy - overwrote affects else if (IS_GOOD(ch)) strcat(k, " good"); } //heebie -- adding invis/sanc/hide/eth mist blend/aura tags for iface apr28, 2012 if (AFF_FLAGGED(ch, AFF_INVISIBLE)) strcat(k, " invis"); if (AFF_FLAGGED(ch, AFF_SANCTUARY)) strcat(k, " sanc"); if (AFF_FLAGGED(to, AFF_SENSE_LIFE)) if (AFF_FLAGGED(ch, AFF_HIDE)) strcat(k, " hidden"); if (AFF_FLAGGED(ch, AFF_MIST)) strcat (k, " mist"); i = k; break; case 'Z': /* affects victim */ sprintf(k, " %ld", AFF_FLAGS((struct char_data *) vict_obj)); if (AFF_FLAGGED(to, AFF_DETECT_ALIGN)) { if (IS_EVIL((struct char_data *) vict_obj)) strcat(k, " evil"); else if (IS_GOOD((struct char_data *) vict_obj)) strcat(k, " good"); } //heebie -- adding invis/sanc/hide/eth mist blend/aura tags for iface apr28, 2012 if (AFF_FLAGGED((struct char_data *) vict_obj, AFF_INVISIBLE)) strcat(k, " invis"); if (AFF_FLAGGED((struct char_data *) vict_obj, AFF_SANCTUARY)) strcat(k, " sanc"); if (AFF_FLAGGED(to, AFF_SENSE_LIFE)) if (AFF_FLAGGED((struct char_data *) vict_obj, AFF_HIDE)) strcat(k, " hidden"); if (AFF_FLAGGED((struct char_data *) vict_obj, AFF_MIST)) strcat (k, " mist"); i = k; break; case 'l': /* get position of character */ sprinttype(GET_POS(ch), position_types, k, sizeof(k)); i = k; break; case 'L': /* get position of victim */ sprinttype(GET_POS((const struct char_data *) vict_obj), position_types, k, sizeof(k)); i = k; break; case 'x': /* get the real name */ i = PC_PERS(ch,to); break; case 'X': /* get the real name */ CHECK_NULL(vict_obj, PC_PERS((const struct char_data *) vict_obj, to)); break; case 'i': /* get the mob unique id number */ sprintf(k,"%i", GET_MOB_UNIQID(ch)); i = k; break; case 'I': /* get the mob unique id number */ sprintf(k,"%i", GET_MOB_UNIQID((const struct char_data *) vict_obj)); i = k; break; case 'n': /* get the name or description */ i = PERS(ch, to); break; case 'N': /* get the name or description */ CHECK_NULL(vict_obj, PERS((const struct char_data *) vict_obj, to)); break; case 'm': /* him, her */ i = HMHR(ch); break; case 'M': /* him, her */ CHECK_NULL(vict_obj, HMHR((const struct char_data *) vict_obj)); break; case 's': /* his, hers */ i = HSHR(ch); break; case 'S': /* his, hers */ CHECK_NULL(vict_obj, HSHR((const struct char_data *) vict_obj)); break; case 'e': /* he, she */ i = HSSH(ch); break; case 'E': /* he, she */ CHECK_NULL(vict_obj, HSSH((const struct char_data *) vict_obj)); break; case 'h': /* health */ sprintf(k,"%i", GET_HIT_PERCENT(ch)); i = k; break; case 'H': /* health */ sprintf(k,"%i", GET_HIT_PERCENT((const struct char_data *) vict_obj)); i = k; break; case 'o': /* object name */ CHECK_NULL(obj, OBJN(obj, to)); break; case 'O': /* object name */ CHECK_NULL(vict_obj, OBJN((const struct obj_data *) vict_obj, to)); break; case 'p': /* object short description */ CHECK_NULL(obj, OBJS(obj, to)); break; case 'P': /* object short description */ CHECK_NULL(vict_obj, OBJS((const struct obj_data *) vict_obj, to)); break; case 'a': /* object adjective lowercase */ CHECK_NULL(obj, SANA(obj)); break; case 'A': /* object adjective lowercase */ CHECK_NULL(vict_obj, SANA((const struct obj_data *) vict_obj)); break; case 'T': CHECK_NULL(vict_obj, (const char *) vict_obj); break; case 'F': CHECK_NULL(vict_obj, fname((const char *) vict_obj)); break; /* uppercase previous word */ case 'u': for (j=buf; j > lbuf && !isspace((int) *(j-1)); j--); if (j != buf) *j = UPPER(*j); i = ""; break; /* uppercase next word */ case 'U': uppercasenext = TRUE; i = ""; break; case '$': i = "$"; break; default: log("SYSERR: Illegal $-code to act(): %c", *orig); log("SYSERR: %s", orig); i = ""; break; } while ((*buf = *(i++))) { if (uppercasenext && !isspace((int) *buf)) { *buf = UPPER(*buf); uppercasenext = FALSE; } buf++; } orig++; } else if (!(*(buf++) = *(orig++))) { break; } else if (uppercasenext && !isspace((int) *(buf-1))) { *(buf-1) = UPPER(*(buf-1)); uppercasenext = FALSE; } } //*(--buf) = '\r'; //*(++buf) = '\n'; //*(++buf) = '\0'; write_to_output(to->desc, "%s\r\n", CAP(lbuf)); }

Please Log in or Create an account to join the conversation.

More
27 Feb 2019 22:33 #8336 by thomas
Replied by thomas on topic Segmentation Fault.
There's still something odd here.

This function call
Code:
act("<art ~ $c >", FALSE, d->character, 0, 0, TO_CHAR);
is being expanded to
Code:
lbuf = "<art ~ save"

And there's really nothing that could do that in this code!

We've clearly hit the $c case, obvious both from the call point above and from the value of orig (="c >"). Since the $c translation is into a set of numbers (all things happening in the get_art() function are adding numbers to a string), where does this "save" come from?

Now would be a good time for a debugging session; you have a reproducible problem in a limited subset of the code base.
The tutorial we have on this site is only a very, very small subset of the gdb program. Check out this handy quickstart guide: web.eecs.umich.edu/~sugih/pointers/gdbQS.html

Fire up the mud through gdb and set a break point at the line with i = get_art(ch);. This is done with break comm.c:2630 (with the correct line number, of course). Log in to the mud, and you will trigger the breakpoint. At this point, the i var is not set to anything relevant, because the line hasn't run yet.
Use the next command to step over the function call. Now print i and perhaps as important print *i will help you see what the i var is at this time. If it is 0 or 1, crash (continue) and start over, this time using step instead of next to step into the get_art() function to see where it suddenly changes.

With a little luck, you'll soon find out how that "save" got into your output. As you might deduct from this post, I can't really help you from here.



Another thing, probably unrelated: the k buffer is too small. It's possible to overflow it given many affects. Expand it to 60 bytes and it should be enough.

Please Log in or Create an account to join the conversation.

Time to create page: 0.220 seconds