Segmentation Fault.

  • timeba
  • Topic Author
  • Offline
  • Fresh Boarder
  • Fresh Boarder
More
3 months 3 days ago #8320 by timeba
Segmentation Fault. was created by timeba
Hey guys, first time poster here. I'm pretty new to the C language but have moderate experience with php.

I have run into a segmentation fault when my user logs into the game.

The section of code where the error is located [comm.c:2631] is stock code that looks unchanged from the source. This mud is heavily customized (graphical interface and mysql db) and I recently became the new admin of it (nostalgia lol).

I followed the guide that you guys have posted here and attached my gdb output, if anyone is willing to help point me in the right direction I would greatly appreciate it!

Feb 21 02:28:06 :: Time (level 34) has 21 objects (max 30).

Program received signal SIGSEGV, Segmentation fault.
0x0000555555593f75 in perform_act (orig=0x5555555e24b1 "c >", ch=0x55555606aed0, obj=0x0, vict_obj=0x0, to=0x55555606aed0) at comm.c:2631
warning: Source file is more recent than executable.
2631 while ((*buf = *(i++)))
(gdb) bt
#0 0x0000555555593f75 in perform_act (orig=0x5555555e24b1 "c >", ch=0x55555606aed0, obj=0x0, vict_obj=0x0, to=0x55555606aed0) at comm.c:2631
#1 0x00005555555b2add in nanny (d=0x555556069150, arg=<optimized out>) at interpreter.c:1858
#2 0x00005555555972db in game_loop (mother_desc=3) at comm.c:768
#3 0x0000555555597516 in init_game (port=<optimized out>) at comm.c:385
#4 0x00005555555613c6 in main (argc=2, 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 = "\033\336\377\377\377\177\000\000\301\274\377\377\377\177\000\000\033\336\377\377"
i = 0x1 <error: Cannot access memory at address 0x1>
lbuf = "<art ~ save\000en;drink canteen;drink canteen;eat waybread", '\000' <repeats 25 times>, "\340\276\377\377\377\177\000\000$\016\362\366\377\177\000\000p\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>, "\300b\322UUU\000\000\001\000\000\000\000\000\000\000z\026\\UUU\000\000\340\276\377\377\377\177\000\000\a\335\\UUU\000\000\001\000\000\000\000\000\000\000"...
buf = 0x7fffffffbcc7 "save"
j = <optimized out>
uppercasenext = 0 '\000'
(gdb) up
#1 0x00005555555b2add in nanny (d=0x555556069150, arg=<optimized out>) at interpreter.c:1858
1858 act("<art ~ $c >", FALSE, d->character, 0, 0, TO_CHAR);
(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) info local
load_room = <optimized out>
load_result = 1
dt = <optimized out>
clan_num = <optimized out>
i = 0
(gdb) up
#2 0x00005555555972db in game_loop (mother_desc=3) at comm.c:768
768 nanny(d, comm);
(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) 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 = 1550716083, tv_usec = 70878}
opt_time = {tv_sec = 0, tv_usec = 100000}
process_time = {tv_sec = 0, tv_usec = 144}
temp_time = {tv_sec = 0, tv_usec = 99856}
before_sleep = {tv_sec = 1550716082, tv_usec = 971022}
now = {tv_sec = 1550716083, tv_usec = 71585}
timeout = {tv_sec = 0, tv_usec = 0}
comm = "1\000me\000aOqIl14\000\177\000\000 \233\036\367\377\177\000\000 \233\036\367\377\177\000\000\320\342\377\377\377\177\000\000r\203]UUU\000\000\060\fn\\\000\000\000\000\000\344i\004\061i\214\032\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\260\343\377\377\377\177\000\000S\204]UUU\000\000\b\000\000\000\060\000\000\000\300\343\377\377\377\177\000\000\000\343\377\377\377\177\000\000\000\344i\004\061i\214\032\320\341\377\377\377\177\000\000\320\340\377\377\377\177\000\000\000\000\000\000\000\000\000\000G\335\360\366\377\177\000\000\300\342\377\377\377\177\000\000\300\242\376\367\377\177\000\000\001\000\000\000\000\000\000\000"...
d = 0x555556069150
next_d = 0x0
pulse = <optimized out>
missed_pulses = 0
maxdesc = <optimized out>
aliased = 0
(gdb) up
#3 0x0000555555597516 in init_game (port=<optimized out>) at comm.c:385
385 game_loop(mother_desc);
(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) info local
mother_desc = 3
(gdb) up
#4 0x00005555555613c6 in main (argc=2, argv=<optimized out>) at comm.c:332
332 init_game(port);
(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) info local
port = 8080
pos = <optimized out>
dir = 0x5555555ead40 "lib"
(gdb) up
Initial frame selected; you cannot go up.

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

More
3 months 3 days ago #8322 by cunning
Replied by cunning on topic Segmentation Fault.
I only have one issue with this, your source code is newer than your executable. This can give false output when debugging. I am not sure this is your actual crash bug.

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

  • timeba
  • Topic Author
  • Offline
  • Fresh Boarder
  • Fresh Boarder
More
3 months 2 days ago #8323 by timeba
Replied by timeba on topic Segmentation Fault.
Thanks for the reply, I removed bin/circle and then recompiled

gcc -o ../bin/circle -pg act.comm.o act.informative.o act.item.o act.movement.o act.offensive.o act.other.o act.social.o act.wizard.o alias.o ban.o boards.o castle.o clan.o class.o comm.o config.o constants.o db.o fight.o graph.o handler.o house.o interpreter.o limits.o magic.o mail.o mobact.o mob_skills.o modify.o objsave.o olc.o races.o random.o shop.o skills.o spec_assign.o spec_procs.o spell_parser.o spells.o statedit.o utils.o weather.o bsd-snprintf.o -lcrypt -lmysqlclient -lm
make[1]: Leaving directory '/home/mud-service/BA-live/src'
make utils
make[1]: Entering directory '/home/mud-service/BA-live/src'
(cd util; make all)
make[2]: Entering directory '/home/mud-service/BA-live/src/util'
make[2]: Nothing to be done for 'all'.
make[2]: Leaving directory '/home/mud-service/BA-live/src/util'
make[1]: Leaving directory '/home/mud-service/BA-live/src'


Then I ran it under gdb again:

...
Feb 21 23:55:13 :: Resetting #501: Yucca Processing Plant (rooms 50100-50199).
Feb 21 23:55:13 :: Resetting #600: Test zone (rooms 60000-60099).
Feb 21 23:55:13 :: Boot db -- DONE.
Feb 21 23:55:13 :: Signal trapping.
Feb 21 23:55:13 :: Entering game loop.
Feb 21 23:55:13 :: No connections. Going to sleep.
Feb 22 00:13:29 :: New connection. Waking up.
Feb 22 00:13:31 :: timeba [desktop] has connected.
Feb 22 00:14:18 :: timeba logged on as Time [desktop].
Feb 22 00:14:53 :: Time (level 80) has 29 objects (max 30).

Program received signal SIGSEGV, Segmentation fault.
0x0000555555593f85 in perform_act (orig=0x5555555e24b1 "c >",
ch=0x555556067330, obj=0x0, vict_obj=0x0, to=0x555556067330) at comm.c:2631
2631 while ((*buf = *(i++)))
(gdb) bt
#0 0x0000555555593f85 in perform_act (orig=0x5555555e24b1 "c >",
ch=0x555556067330, obj=0x0, vict_obj=0x0, to=0x555556067330) at comm.c:2631
#1 0x00005555555b2aed in nanny (d=0x5555560655b0, 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=2, argv=<optimized out>) at comm.c:332
(gdb) info local
k = "gain.\000\000\000\301\274\377\377\377\177\000\000\033\336\377\377"
i = 0x1 <error: Cannot access memory at address 0x1>
lbuf = "<art ~ save\000en;drink canteen;drink canteen;eat waybread", '\000' <repeats 25 times>, "\340\276\377\377\377\177\000\000$\016\362\366\377\177\000\000p\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>, "\300b\322UUU\000\000\001\000\000\000\000\000\000\000\212\026\\UUU\000\000\340\276\377\377\377\177\000\000\027\335\\UUU\000\000\001\000\000\000\000\000\000\000"...
buf = 0x7fffffffbcc7 "save"
j = <optimized out>
uppercasenext = 0 '\000'
(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) print
The history is empty.
(gdb) up
#1 0x00005555555b2aed in nanny (d=0x5555560655b0, 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) print
The history is empty.
(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 = 1550794474, tv_usec = 94559}
opt_time = {tv_sec = 0, tv_usec = 100000}
process_time = {tv_sec = 0, tv_usec = 8204}
temp_time = {tv_sec = 0, tv_usec = 91796}
before_sleep = {tv_sec = 1550794474, tv_usec = 2763}
now = {tv_sec = 1550794474, tv_usec = 95503}
timeout = {tv_sec = 0, tv_usec = 0}
comm = "1\000me\000aOqIl14\000\177\000\000 \233\036\367\377\177\000\000 \233\036\367\377\177\000\000\320\342\377\377\377\177\000\000\202\203]UUU\000\000a:o\\\000\000\000\000\000zfz$\256\"}\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\260\343\377\377\377\177\000\000c\204]UUU\000\000\b\000\000\000\060\000\000\000\300\343\377\377\377\177\000\000\000\343\377\377\377\177\000\000\000zfz$\256\"}\320\341\377\377\377\177\000\000\320\340\377\377\377\177\000\000\000\000\000\000\000\000\000\000G\335\360\366\377\177\000\000\300\342\377\377\377\177\000\000\300\242\376\367\377\177\000\000\001\000\000\000\000\000\000\000"...
d = 0x5555560655b0
next_d = 0x0
pulse = <optimized out>
---Type <return> to continue, or q <return> to quit---
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) print
The history is empty.
(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) print
The history is empty.
(gdb) up
#4 0x00005555555613c6 in main (argc=2, 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) print
The history is empty.
(gdb) up
Initial frame selected; you cannot go up.
(gdb)

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

More
3 months 1 day ago - 3 months 1 day ago #8328 by thomas
Replied by thomas on topic Segmentation Fault.
Well, somethings up with the i variable.

i = 0x1 <error: Cannot access memory at address 0x1>

i should never be 1. It should either point to NULL or it should point to an empty string (if you pass it an unknown $code or a code with no "string" meaning).
So, we've hit the $c case in perform_act. And that isn't a stock code. Which means that we'll need a bit more info.

What happens in case 'c': ? And please show the expansion of any macros in use there.
Last edit: 3 months 1 day ago by thomas.

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

  • timeba
  • Topic Author
  • Offline
  • Fresh Boarder
  • Fresh Boarder
More
3 months 11 hours ago - 3 months 11 hours ago #8329 by timeba
Replied by timeba on topic Segmentation Fault.
Appreciate the help!

Looks like that section of code is getting the artwork for the GUI.

Here is the section from the gdb error:

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 */


here is the section for *get_art from line 1483 in handler.c:

char *get_art(struct char_data *vict) {
char buf[200];
char *fbuf = buf;
int art_num;
int count;

if (IS_NPC(vict))
art_num = GET_MOB_ART(vict);
else
art_num = GET_PLAYER_ART(vict);


count = sprintf(buf, "%d %d %d", art_num,
GET_RACE(vict), GET_SEX(vict));

/* equipment */
if (!IS_NPC(vict) || MOB_FLAGGED(vict, MOB_SHOW_EQ)) {
/* light */
// if (GET_EQ(vict, WEAR_LIGHT))
// count += sprintf(buf + count, " %d",
// GET_OBJ_ART(GET_EQ(vict, WEAR_LIGHT)));
// else
// count += sprintf(buf + count, " %d", 0);
/* body */
if (GET_EQ(vict, WEAR_BODY))
count += sprintf(buf + count, " %d",
GET_OBJ_ART(GET_EQ(vict, WEAR_BODY)));
else
count += sprintf(buf + count, " %d", 0);
/* head */
if (GET_EQ(vict, WEAR_HEAD))
count += sprintf(buf + count, " %d",
GET_OBJ_ART(GET_EQ(vict, WEAR_HEAD)));
else
count += sprintf(buf + count, " %d", 0);
/* legs */
if (GET_EQ(vict, WEAR_LEGS))
count += sprintf(buf + count, " %d",
GET_OBJ_ART(GET_EQ(vict, WEAR_LEGS)));
else
count += sprintf(buf + count, " %d", 0);
/* feet */
if (GET_EQ(vict, WEAR_FEET))
count += sprintf(buf + count, " %d",
GET_OBJ_ART(GET_EQ(vict, WEAR_FEET)));
else
count += sprintf(buf + count, " %d", 0);
/* hands */
if (GET_EQ(vict, WEAR_HANDS))
count += sprintf(buf + count, " %d",
GET_OBJ_ART(GET_EQ(vict, WEAR_HANDS)));
else
count += sprintf(buf + count, " %d", 0);
/* arms */
if (GET_EQ(vict, WEAR_ARMS))
count += sprintf(buf + count, " %d",
GET_OBJ_ART(GET_EQ(vict, WEAR_ARMS)));
else
count += sprintf(buf + count, " %d", 0);
/* shield */
if (GET_EQ(vict, WEAR_SHIELD))
count += sprintf(buf + count, " %d",
GET_OBJ_ART(GET_EQ(vict, WEAR_SHIELD)));
else
count += sprintf(buf + count, " %d", 0);
/* about */
if (GET_EQ(vict, WEAR_ABOUT))
count += sprintf(buf + count, " %d",
GET_OBJ_ART(GET_EQ(vict, WEAR_ABOUT)));
else
count += sprintf(buf + count, " %d", 0);
/* wield */
if (GET_EQ(vict, WEAR_WIELD))
count += sprintf(buf + count, " %d",
GET_OBJ_ART(GET_EQ(vict, WEAR_WIELD)));
else
count += sprintf(buf + count, " %d", 0);
/* hold */
// if (GET_EQ(vict, WEAR_HOLD))
// count += sprintf(buf + count, " %d",
// GET_OBJ_ART(GET_EQ(vict, WEAR_HOLD)));
// else
// count += sprintf(buf + count, " %d", 0);
/* tattoo */
if (!IS_NPC(vict) && GET_CLAN_RANK(vict))
count += sprintf(buf + count, " %d", GET_CLAN(vict));
else
count += sprintf(buf + count, " %d", 0);
}

return fbuf;
}


here is another on line 79 in handler.h:

char *get_art(struct char_data *ch);


here is another reference to get_art in db.c on line 546:

result = mysql_store_result(db_handle);
if ((row = mysql_fetch_row(result))) { /* update */
char *i, *k;
char j[200];
k = j;
i = get_art(d->character);
while ((*k = *(i++))) k++;


The art located in the mysql db for character Time is
1409 0 1 150532 171205 171959 150801 170762 152159 2556 1453 170023 0

I get the same issue with other characters so I don't believe it is specific to the one character (Time).
Last edit: 3 months 11 hours ago by timeba. Reason: formatting

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

More
3 months 2 hours ago #8330 by thomas
Replied by thomas on topic Segmentation Fault.
Your culprit is the get_art() function. The moment you exit such a function, every allocated buffer is released for reuse, unless it is a static buffer.

So, instead of
char *get_art(struct char_data *vict) {
  char buf[200];
  char *fbuf = buf;

// code writing to buf

  return fbuf;
}
Try this:
char *get_art(struct char_data *vict) {
  static char buf[200];
  *buf = '\0';

// code writing to buf

  return buf;
}
This will allocate the buf variable in another memory section, and it will be reused for all calls to the get_art() function.

Also, please format your code with [ code ] tags instead of [ quote ] tags :P

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

  • timeba
  • Topic Author
  • Offline
  • Fresh Boarder
  • Fresh Boarder
More
2 months 4 weeks ago #8331 by timeba
Replied by timeba on topic Segmentation Fault.
Still running into the same error.

I replaced the code like suggested:
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:
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
2 months 4 weeks ago #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.

  • timeba
  • Topic Author
  • Offline
  • Fresh Boarder
  • Fresh Boarder
More
2 months 4 weeks ago #8333 by timeba
Replied by timeba on topic Segmentation Fault.
Here is perform_act
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
2 months 3 weeks ago - 2 months 3 weeks ago #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:
    default:
	log("SYSERR: Illegal $-code to act(): %c", *orig);
	log("SYSERR: %s", orig);
+     i = "";
	break;
Last edit: 2 months 3 weeks ago by thomas.

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

  • timeba
  • Topic Author
  • Offline
  • Fresh Boarder
  • Fresh Boarder
More
2 months 3 weeks ago #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:
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
2 months 3 weeks ago #8336 by thomas
Replied by thomas on topic Segmentation Fault.
There's still something odd here.

This function call
act("<art ~ $c >", FALSE, d->character, 0, 0, TO_CHAR);
is being expanded to
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: 1.999 seconds